学习案例:热血江湖

使用环境:Visual Studio 2019

学习使用的工具:逆向工具集

注:更新日志:

  • 1.0:最新版人物信息基址:0x02C166D8;最新版背包存放基址:0x02E3B3E4
  • 2.0:最新版物品使用call 为0x00838480
  • 3.0:
    • 人物基址:0x02C176D8‬;
    • 背包存放基址:0x02E3C3E4;
    • 游戏主窗口基址:0x01195F88;
    • 使用物品的CALL:0x008384F0;
    • 人物动作基址:0x02E3CD58;
    • 动作使用的CALL:0x007139E0;
    • 所有对象数组:0x2E64A28;
    • 怪物基址:0x427FBA0
    • 角色对象基址:0x427FBA0
  • 4.0:最新版人物基址:
    • 游戏人物的基址:0x02C166D8
    • 游戏背包的基址存放地址:0x02E3B3E4
    • 添加背包物品使用CALL 的地址:0x008384A0
    • 游戏主窗口基址:0x01194F88
    • 怪物列表基址:0x427EBA0
    • 人物动作基址:0x02E3BD58
    • 人物动作使用的CALL 的基址:0x00713990
    • 角色对象的基址:0x427EBA0
    • 所有对象的数组:0x2E63A28
    • 攻击武功基址:0x02E3CF64
    • 辅助武功基址:0x02E3CF68
    • 添加技能到快捷栏的基址:0x00849780
    • 选中物品基址:0x0125255C
    • 快捷栏基址:0x02E3CF08
    • 寻路基址:0x2E63A24
    • 仓库基址:0x02E4492C
    • 装备基址:0x02E3B3E0
    • 打开NPC菜单CALL:0x007D5130
    • 商店基址:0x02E65600
    • 购买/出售 物品的基址:0x1195000
    • 购买/出售 物品的CALL:0x004F8380
    • 存取多个物品的基址:0x1195000
    • 存取多个物品的CALL:0x004F8380
    • 存取指令:
      • 存放:0xEB1C5211
      • 取出:0x00000000
    • 操作类型:
      • 存取指令:0x008C0094
      • 购买/出售指令:0x00880092

人物属性数据分析

注:

  • 一般游戏开发的时候,相关的数据都是放到一个结构或者是一个类中,那么这些数据的内存地址相距的比较近;

  • 一般内存地址使用CE工具逆向出来后表示为Client.exe+278A75C,表示软件地址加上偏移量为其基址

HP值和MP值

  • 生命值PH: Client.exe+278A75C = 02B8A758
  • 内功值MH: Client.exe+278A75C = 02B8A75C

金币值

  • 进行商品的买卖实现金币值的变动
  • 基址:Client.exe+278A7BC = 02B8A7BC

其他人物属性分析

  • OD软件的使用
    • 使用dd 02B8A758 查找到人物属性基址块
  • 人物属性值以及对应的内存地址
  • 基址 02B8A6D8
    • +0:人物名字
    • +80:生命值(红/HP)
    • +84:内功值(蓝/MP)
    • +88:愤怒值
    • +8C:最大生命值
    • +90:最大内功值
    • +94:最大值愤怒值
    • +98:当前经验值
    • +A0:升级到下一级要的经验值
    • 势力
    • +36:名声
    • +34:一字节空间表示等级
    • +35:一字节空间表示 几转
    • +AC:历练
    • 制造
    • 熟练度
    • 灵兽持有
    • 精力
    • +C8:攻击
    • 武器命中
    • +CC:防御
    • 武器防御
    • +D0:命中
    • 对人战斗
    • +D4:回避
    • 对怪攻击
    • 武功回避
    • 对怪防御
    • +B0:心
    • +B4:气
    • +B8:体
    • +BC:魂
    • +E4:金币值
  • 气功值分析
    • 气功点数:基址 + F0 = 02b8a7c8
    • 第num个气功的点数:(一个字节)02B8A6D8+0f0+4*num
    • 可能是第num个气功的ID(没有就为0):02B8A6D8+0f0+4*num+2

通过注入游戏进程读取游戏内数据

  • 注入DLL

    • 创建MFC DLL

      创建MFC_DLL

  • 在添加窗口后,需要进行配置,才能在动态链接库注入后显示窗口

    • 为窗口添加Class

    • 修改MFC_DLL.cpp的代码

      • // MFC_DLL.cpp: 定义 DLL 的初始化例程。
        //#include "pch.h"
        #include "framework.h"
        #include "MFC_DLL.h"// 包含含有主窗口的class1的头文件
        #include "CMainDialogWnd.h"#ifdef _DEBUG
        #define new DEBUG_NEW
        #endifBEGIN_MESSAGE_MAP(CMFCDLLApp, CWinApp)
        END_MESSAGE_MAP()// CMFCDLLApp 构造CMFCDLLApp::CMFCDLLApp()
        {// TODO:  在此处添加构造代码,// 将所有重要的初始化放置在 InitInstance 中
        }// 唯一的 CMFCDLLApp 对象CMFCDLLApp theApp;// CMFCDLLApp 初始化// 定义全局的窗口变量
        CMainDialogWnd* PMainDialog;BOOL CMFCDLLApp::InitInstance()
        {CWinApp::InitInstance();// 添加显示窗口的代码// 创建对象,划分空间PMainDialog = new CMainDialogWnd;//DoModal 是以阻塞的方式来运行PMainDialog->DoModal();// 释放空间delete PMainDialog;return TRUE;
        }
    • 使用注入工具讲编译生成的DLL 注入到游戏进程中

      • 注:DoModal() 函数是以阻塞的方式去执行的,所以会造成线程阻塞

      • 解决方式:将DoModal() 放到新的线程去执行

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-poCsOk99-1590415578738)(https://i.loli.net/2019/07/11/5d270c58f2d0b26607.png)]

      • 实现窗口关闭后自动释放DLL

    使用代码实现动态连接库的注入

    • 使用到的windows API

      • HWND FindWindow(lpClassName, lpWindowNAme)
        • 通过类名指针或窗口名指针获取窗口句柄
      • DWORD GetWindowThreadProcessId(hwnd(窗口句柄), lpdwProcessId)
        • 获取窗口线程句柄的ID(lpdwProcessId)
      • HANDLE WINAPI OpenProcess(dwDesiredAccess(访问权限), bInheritHandle, dwProcessId)
        • 开启并创建一个本地进程
      • LPVOID WINAPI VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect)
        • 分配内存空间
      • BOOL WINAPI WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten)
        • 向内存中写入数据
      • HANDLE WINAPI CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId)
        • 为进程创建一个线程
      • DWORD WINAPI WaitForSingleObject(hHandle, dwMilliseconds)
        • 等待单个对象执行后再进行操作
      • BOOL WINAPI CloseHandle(hObject)
        • 关闭句柄
      • BOOL WINAPI VirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType)
        • 释放内存空间
      • BOOL WINAPI CloseHandle(hObject)
        • 关闭句柄

      代码


#include <iostream>
#include <windows.h>
#define GameClassName "D3D Window"
#define DllPath "D:\\c_work\\MFC_DLL\\Debug\\MFC_DLL.dll"using namespace std;void InjectDll() {DWORD pid = 0;HANDLE hProcess = NULL;LPDWORD lpAddr = NULL; // 获取远程分配成功的地址DWORD size = NULL;HANDLE threadHandle = NULL;// 获取游戏窗口句柄HWND GameH = FindWindow((LPCTSTR)GameClassName, NULL);if (GameH != 0) {//句柄获取成功// 获取进程PIDGetWindowThreadProcessId(GameH, &pid);if (pid != 0) {// PID 获取成功// 获取进程句柄// 开启所以权限打开进程hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE ,pid);if (hProcess != NULL) {// 打开进程成功// 分配内存空间,写入动态链接库的全路径名//D:\\c_work\\MFC_DLL\\Debug\\MFC_DLL.dlllpAddr = (LPDWORD)VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_READWRITE);if (lpAddr != NULL) {// 地址分配成功, 写入DLL 的全路径WriteProcessMemory(hProcess, lpAddr, DllPath, strlen(DllPath) + 1, &size);if (size >= strlen(DllPath)) {threadHandle = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryA, lpAddr, NULL, NULL);// 等待注入DLL 的线程执行完再执行下一步(等待的进程句柄, 等到多少毫秒)WaitForSingleObject(threadHandle, 0xFFFFFFFF);// 关闭线程CloseHandle(threadHandle);// 释放进程VirtualFreeEx(hProcess, lpAddr, 256, MEM_DECOMMIT);// 关闭句柄CloseHandle(hProcess);// 清除内存数据}else {cout << "写入DLL 失败" << endl;}}else {cout << "地址分配失败" << endl;}}else {cout << "打开进程失败" << endl;}}else {cout << "获取PID 失败" << endl;}}else {cout << "获取窗口句柄失败" << endl;}}int main()
{// 添加注入DLL 代码cout << "开始注入DLL" << endl;InjectDll();cout << "注入DLL结束" << endl;}
  • 步骤
    1. 获取窗口对应的进程的PID
    2. 根据PID 获取进程
    3. 获取游戏进程的PID
    4. 根据PID 获取进程
    5. 在目标进程分配内存空间,方便写入DLL 全路径
    6. 将DLL 全路径写入到目标进程
    7. 远程注入DLL
    8. 等待目标进程执行完成
    9. 释放进程空间
    10. 关闭线程句柄

整合游戏内数据

  • 整数

    • QWORD 类型变量 nq前缀 //8字节 无符号整数 不能表示负数
    • DWORD 类型变量 nd前缀 //4字节 无符号整数 不能表示负数
    • WORD 类型变量 nw前缀 //2字节 无符号整数 不能表示负数
    • BYTE 类型变量 nb前缀 //1字节 无符号整数 不能表示负数
    • int 带符号类型 ni前缀 //4字节 带符号整数 可表示正负数
    • _int64 带符号整型 ni64 //8字节 带符号整数 不能表示负数
    • UINT 类型变量 ui前缀 // 无符号整数 一般是4字节
    • //浮点数
    • float 单精度浮点数 fl前缀
    • double 双精度浮点数 fd前缀
  • 字符串

    • char*和char [] sz前缀 //PCHAR szp
  • CString str前缀

  • 结构名 T开头全大写

  • 类名 C开头单词首字大写

整合游戏数据步骤

  1. 新建解决方案GameData

  2. 创建头文件BaseGame.h和 StructGame.h


    • BaseGame.h
    #pragma once// 游戏人物的基址
    #define BaseRole 0x02B8A6D8

    • StructGame.h
    #pragma once
    #include <windows.h>
    typedef unsigned __int64 QWORD;
    // 游戏结构以及偏移量的管理typedef struct TROLE_PROPERTY {// +0:人物名字char* szRoleName;// + 80:生命值(红 / HP)DWORD ndRoleHP;// + 84:内功值(蓝 / MP)DWORD ndRoleMP;// + 88:愤怒值DWORD ndRoleAnger;// + 8C:最大生命值DWORD ndRoleMaxHP;// + 90:最大内功值DWORD ndRoleMaxMP;// + 94:最大值愤怒值QWORD nqRoleMaxAnger;// + 98:当前经验值QWORD nqRoleExprienceNow;// + A0:升级到下一级要的经验值DWORD ndRoleExperienceNext;// + 36:名声char* szReputation;// + 34:一字节空间表示等级BYTE nbClassValue;// + 35:一字节空间表示 几转BYTE nbJZ;// + AC:历练DWORD ndExprience;// + C8:攻击DWORD ndAttack;// + CC:防御DWORD ndDefense;// + D4:回避DWORD ndAvoid;// + B0:心DWORD ndHeart;// + B4:气DWORD ndGas;// + B8:体DWORD ndBody;// + BC:魂DWORD ndSoul;// + E4:金币值QWORD nqMoney;// 气功DWORD ndQg[32];TROLE_PROPERTY* GetData();char* GetRoleName();}_TROLE_PROPERTY;
  3. 创建源文件StructGame.cpp


    • StructGame.cpp
    #include "StructGame.h"
    #include "BaseGame.h"
    TROLE_PROPERTY* TROLE_PROPERTY::GetData()
    {// 添加异常处理try {// +0:人物名字szRoleName = (char*)BaseRole;// + 80:生命值(红 / HP)ndRoleHP = (DWORD)(BaseRole + 0x80);// + 84:内功值(蓝 / MP)ndRoleMP = (DWORD)(BaseRole + 0x84);// + 88:愤怒值ndRoleAnger = (DWORD)(BaseRole + 0x88);// + 8C:最大生命值ndRoleMaxHP = (DWORD)(BaseRole + 0x8c);// + 90:最大内功值ndRoleMaxMP = (DWORD)(BaseRole + 0x90);// + 94:最大值愤怒值nqRoleMaxAnger = (QWORD)(BaseRole + 0x94);// + 98:当前经验值nqRoleExprienceNow = (QWORD)(BaseRole + 0x98);// + A0:升级到下一级要的经验值ndRoleExperienceNext = (DWORD)(BaseRole + 0xA0);// + 36:名声szReputation = (char*)(BaseRole + 0x36);// + 34:一字节空间表示等级nbClassValue = *(BYTE*)(BaseRole + 0x34);// + 35:一字节空间表示 几转nbJZ = *(BYTE*)(BaseRole + 0x35);// + AC:历练ndExprience = (DWORD)(BaseRole + 0xac);// + C8:攻击ndAttack = (DWORD)(BaseRole + 0xc8);// + CC:防御ndDefense = (DWORD)(BaseRole + 0xcc);// + D4:回避ndAvoid = (DWORD)(BaseRole + 0xd4);// + B0:心ndHeart = (DWORD)(BaseRole + 0xb0);// + B4:气ndGas = (DWORD)(BaseRole + 0xb4);// + B8:体ndBody = (DWORD)(BaseRole + 0x8c);// + BC:魂ndSoul = (DWORD)(BaseRole + 0xbc);// + E4:金币值nqMoney = (QWORD)(BaseRole + 0xe4);for (int i = 0; i < 32; i++) {ndQg[i] = *(BYTE*)(BaseRole + 0xf0 + 4 * (i + 1));}}catch (...) {// 处理所有的异常OutputDebugStringA("读取人物数据异常\r\n");}return this;
    }// 获取角色的名称、
    char* TROLE_PROPERTY::GetRoleName() {return GetData()->szRoleName;
    }

VS2019 导入静态链接库(lib)、配置输出路径的方式

  • 配置链接库路径

    • 配置 附加包含目录

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-auIb3GNc-1590415578743)(https://i.loli.net/2019/07/12/5d282a710f95f93418.png)]

    • 配置 添加库目录

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E3RCrCQr-1590415578745)(https://i.loli.net/2019/07/12/5d282aa5ca58875840.png)]

  • 配置编译输出路径

    • 修改输出目录

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FaFEsBsS-1590415578747)(https://i.loli.net/2019/07/12/5d282b31d492535906.png)]

游戏中的物品使用

  • 在游戏中,对应的物品都会有一个结构/类,包含了物品的一些信息

  • 使用物品实际上调用了应该CALL

以金疮药为例
  • 寻CALL 的过程

    • 使用CE工具找到对象地址指针

    • 去查看访问改指针的地址

    • 使用OD 工具对这些地址进行动态调试

    • 远程注入代码(使用金疮药)

    • push 1
      push 1
      push 0
      mov ecx, 21DF06D0
      call 00838470
      
背包数据的分析
  • 背包在游戏中一般会写成应该结构体/类来存放物品对象
  • 物品对象在背包中使用数组的形式存在
  • 汇编中数组的访问方式一般是 数组基址 + 4 * i(’ i '为数组下标)
  • 查找背包数组基址:
    • 找到背包的物品格
    • 反复讲里面的物品拿出/放入
    • 使用CE工具进程分析
  • 结果
    • 存放背包基址的内存空间:0x02DAF3E4
    • 第num 个格子的数据获取
      • *背包基址+num*4+0x43C
      • 注:0x43 是偏移量
      • 物品对象指针 + 0x64 = 物品名字
      • 物品对象指针 + 0xf9 = 对物品的描述
      • 物品对象指针 + 0xC4C = 物品剩余数量

封装背包数据

封装背包结构体

// 物品结构
typedef struct TBACKPACK_GOODS {// *物品对象指针 + 0x64 = 物品名字char* szGoodsName;// * 物品对象指针 + 0xf9 = 对物品的描述char* szGoodsIntro;// * 物品对象指针 + 0xC4C = 物品剩余数量DWORD ndGoodsNum;} _TBACKPACK_GOODS;// 背包结构
typedef struct TGOODSLIST_PROPERTY {_TBACKPACK_GOODS mtGoodsList[nGoodsNum];// 对数据的初始化TGOODSLIST_PROPERTY* getData();
}_TGOODSLIST_PROPERTY;

实现初始化方法(getDate())

TGOODSLIST_PROPERTY* TGOODSLIST_PROPERTY::getData()
{// 通过获取背包基址对每样物品进行分析// *物品对象指针 + 0x64 = 物品名字
#define GOODSNAME 0x64
// * 物品对象指针 + 0xf9 = 对物品的描述
#define GOODSINTRO 0xf9
// * 物品对象指针 + 0xC4C = 物品剩余数量
#define GOODSNUM 0xc4c// 背包公式: ndBaseAddr + num*4 + 0x43ctry {// 读取背包基址DWORD ndBase = *(DWORD*)(BaseBackpack);// 第一个物品的地址DWORD ndFirstGoodsBase = ndBase + 4 * 0 + 0x43c;// 第一个物品的对象DWORD ndObj = NULL;for (int i = 0; i < nGoodsNum; i++) {ndObj = *(DWORD*)(ndFirstGoodsBase + 4 * i); // 取出第i个对象的地址if (ndObj == NULL) {// 如果读取数据为0===> 背包这一格没有物品this->mtGoodsList[i].ndGoodsNum = 0;continue;}// 读取物品的名字this->mtGoodsList[i].szGoodsName = (char*)(ndObj + GOODSNAME);// 读取物品的介绍this->mtGoodsList[i].szGoodsIntro = (char*)(ndObj + GOODSINTRO);// 读取物品的剩余数量this->mtGoodsList[i].ndGoodsNum = *(DWORD*)(ndObj + GOODSNUM);}}catch (...) {// 处理所有异常OutputDebugStringA("读取背包数据异常\r\n");MessageBox(NULL, "读取背包数据异常(StructGame)", "Error", MB_OK);}return this;
}

调试调用

void CMainDialogWnd::OnBnClickedButton1()
{TROLE_PROPERTY role;TROLE_PROPERTY* r = role.GetData();TGOODSLIST_PROPERTY goods;TRACE("GameDebug:我的调试信息\r\n");TRACE("GameDebug: 人物名=%s\r\n", r->GetRoleName());TRACE("GameDebug: 人物等级=%d\r\n", r->nbClassValue);TRACE("GameDebug: 人物名声=%s\r\n", r->szReputation);TRACE("GameDebug: 人物血量HP=%d//%d\r\n", r->ndRoleHP, r->ndRoleMaxHP);TRACE("GameDebug: 人物内功MP=%d//%d\r\n", r->ndRoleMP, r->ndRoleMaxMP);TRACE("GameDebug: 人物愤怒值=%d\r\n", r->ndRoleAnger);TRACE("GameDebug: 人物金币=%d\r\n", r->nqMoney);TGOODSLIST_PROPERTY* g = goods.getData();try {for (int i = 0; i < nGoodsNum; i++) {if (g->mtGoodsList[i].ndGoodsNum == 0) {continue;}TRACE("GameDebug: 人物第%d格数据:%s\r%s\r%d\r\n", i,g->mtGoodsList[i].szGoodsName,g->mtGoodsList[i].szGoodsIntro,g->mtGoodsList[i].ndGoodsNum);}}catch (...) {MessageBox(TEXT("读取背包数据异常(Dialog)"), TEXT("Error"), MB_OK);}// 进行数据修改
}

文件结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wL4Vw681-1590415578751)(https://i.loli.net/2019/07/23/5d3707690948b56906.png)]

背包物品的使用

之前Call 的分析

push 背包物品下标
push 1
push 0
mov ecx, 背包基址
call 00838470

封装函数

UseGoods(char* szGoodsName)
{// 若存在则使用它return 1;
}

背包物品使用代码

  • 定义基址
// 添加背包物品使用CALL 的地址 ===> 通过背包物品下标进行物品的使用
#define BaseCall_UseGoodsForIndex 0x00838470
  • 定义结构
// 背包结构
typedef struct TGOODSLIST_PROPERTY {// 背包列表_TBACKPACK_GOODS mtGoodsList[nGoodsNum];// 对数据的初始化TGOODSLIST_PROPERTY* getData();// 使用背包物品int UseGoodsForIndex(DWORD ndIndex);// 通过名字查询下标,存在返回下标,不存在返回FALSEint GetGoodsIndexByName(char* szGoodsName);// 根据物品的名字进行使用int UseGoodsForName(char* szGoodsName);
}_TGOODSLIST_PROPERTY;
  • 实现方法
// 通过物品下标使用物品
int TGOODSLIST_PROPERTY::UseGoodsForIndex(DWORD ndIndex) {try {// 使用内联汇编__asm {mov eax, ndIndexpush eaxpush 1push 0// 读取背包地址mov ecx, [BaseBackpack]mov eax, BaseCall_UseGoodsForIndexcall eax}}catch (...) {OutputDebugStringA("物品使用异常");}return TRUE;}int TGOODSLIST_PROPERTY::UseGoodsForName(char* szGoodsName)
{// 查找物品的下标DWORD ndIndex = this->GetGoodsIndexByName(szGoodsName);if (ndIndex != -1) {this->UseGoodsForIndex(ndIndex);return TRUE;}return FALSE;
}int TGOODSLIST_PROPERTY::GetGoodsIndexByName(char* szGoodsName) {// 遍历整个背包,看是否存在该物品TGOODSLIST_PROPERTY* g = this->getData();// 初始化背包结构for (int i = 0; i < nGoodsNum; i++) {// 比较字符串,判断该物品是否存在if (strcmp(szGoodsName, g->mtGoodsList[i].szGoodsName) == 0) {return i;}}return -1;
}
  • 调用方法,实现物品的使用
if (g->UseGoodsForName("回城符(泫勃派)")) {TRACE("GameDebug: 使用 回城符(泫勃派) 成功");}
  • 文件结构

编写自定义的DbgPrintMine方法用于打印格式化调式信息

// DbgPrintMine.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <windows.h>
using namespace std;// 定义变参函数
void DbgPrintMine(char* pszFormat, ...) {
#ifdef _DEBUG// 如果在DEBUG 版本下才执行以下代码// 定义listva_list argList;// 初始化listva_start(argList, pszFormat);// 定义字符串缓冲区char szBufFormat[0x1000];// 定义调试前缀char szBufFormat_Game[0x1008] = "Game:";// 获取参数 va_arg(list, paramType)/*int i = va_arg(argList, int);int j = va_arg(argList, int);char* szK = va_arg(argList, char*);*/vsprintf_s(szBufFormat, pszFormat, argList);strcat_s(szBufFormat_Game, szBufFormat);OutputDebugStringA(szBufFormat_Game);// 清除listva_end(argList);
#endif}int main()
{DbgPrintMine((char*)"%d, %d, %s\n", 1, 2, "贾谨荣");system("pause");
}

注:多线程访问数据造成异常的原因以及解决方式

造成异常的原因:

  • 游戏主线程与外挂线程同时访问共享数据区域,造成程序异常
  • 让两个线程依次使用共享数据或者将注入线程到主线程

模拟游戏主线程和辅助线程同时执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xyqK7p9r-1590415578757)(https://i.loli.net/2019/07/25/5d396c0068fd480536.png)]

  • 代码
// 定义变参函数
void DbgPrintMine(char* pszFormat, ...) {
#ifdef _DEBUG// 如果在DEBUG 版本下才执行以下代码// 定义listva_list argList;// 初始化listva_start(argList, pszFormat);// 定义字符串缓冲区char szBufFormat[0x1000];// 定义调试前缀char szBufFormat_Game[0x1008] = "Game:";// 获取参数 va_arg(list, paramType)/*int i = va_arg(argList, int);int j = va_arg(argList, int);char* szK = va_arg(argList, char*);*/vsprintf_s(szBufFormat, pszFormat, argList);strcat_s(szBufFormat_Game, szBufFormat);OutputDebugStringA(szBufFormat_Game);// 清除listva_end(argList);
#endif}DWORD g_ndGameData[10] = { 111, 222, 333, 444, 555, 666, 777, 888, 999, 000 };
DWORD* g_pndGameData[10];void UseGoods(char* szGoodsName) {for (int i = 0; i < 10; i++) {DbgPrintMine("%s, %d\r\n", szGoodsName, *g_pndGameData[i]);Sleep(1 * 1000);}return;
}DWORD WINAPI GameMainThreadProc(LPVOID lpData) {while (TRUE) {// 初始化内存memset(g_pndGameData, NULL, sizeof(g_pndGameData));for (int i = 0; i < 10; i++) {g_pndGameData[i] = g_ndGameData + i; // &g_ndGameData[i]Sleep(1000);}// 物品使用的CALLUseGoods("游戏主线程");}
}DWORD WINAPI GameMyThreadProc(LPVOID lpData) {while (TRUE) {// 初始化内存UseGoods("外挂线程:222");Sleep(1 * 1000);}
}// 游戏主线程
void CDataExceptionTestDlg::OnBnClickedButton1()
{// TODO: 在此添加控件通知处理程序代码CreateThread(NULL, NULL, GameMainThreadProc, NULL, 0, NULL);
}// 外挂线程
void CDataExceptionTestDlg::OnBnClickedButton2()
{// TODO: 在此添加控件通知处理程序代码CreateThread(NULL, NULL, GameMyThreadProc, NULL, 0, NULL);
}
  • 异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EWZscljm-1590415578759)(https://i.loli.net/2019/07/25/5d396c8ded2eb52094.png)]

解决方式

  • 将程序注入到主线程

  • 使用临界区

    • 1

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EtlphK7R-1590415578762)(https://i.loli.net/2019/07/25/5d3970363d1b650747.png)]

    • 2、代码

      
      // 定义变参函数
      void DbgPrintMine(char* pszFormat, ...) {
      #ifdef _DEBUG// 如果在DEBUG 版本下才执行以下代码// 定义listva_list argList;// 初始化listva_start(argList, pszFormat);// 定义字符串缓冲区char szBufFormat[0x1000];// 定义调试前缀char szBufFormat_Game[0x1008] = "Game:";// 获取参数 va_arg(list, paramType)/*int i = va_arg(argList, int);int j = va_arg(argList, int);char* szK = va_arg(argList, char*);*/vsprintf_s(szBufFormat, pszFormat, argList);strcat_s(szBufFormat_Game, szBufFormat);OutputDebugStringA(szBufFormat_Game);// 清除listva_end(argList);
      #endif}// 定义临界区;
      CRITICAL_SECTION lpCriticalSection;DWORD g_ndGameData[10] = { 111, 222, 333, 444, 555, 666, 777, 888, 999, 000 };
      DWORD* g_pndGameData[10];void UseGoods(char* szGoodsName) {// 进入临界区EnterCriticalSection(&lpCriticalSection);for (int i = 0; i < 10; i++) {DbgPrintMine("%s, %d\r\n", szGoodsName, *g_pndGameData[i]);Sleep(1 * 100);}// 离开临界区LeaveCriticalSection(&lpCriticalSection);return;
      }DWORD WINAPI GameMainThreadProc(LPVOID lpData) {while (TRUE) {// 进入临界区EnterCriticalSection(&lpCriticalSection);// 初始化内存memset(g_pndGameData, NULL, sizeof(g_pndGameData));for (int i = 0; i < 10; i++) {g_pndGameData[i] = g_ndGameData + i; // &g_ndGameData[i]Sleep(1000);}// 离开临界区LeaveCriticalSection(&lpCriticalSection);// 腾出有点时间片给外挂线程使用Sleep(1 * 1000);// 物品使用的CALLUseGoods("游戏主线程");}
      }DWORD WINAPI GameMyThreadProc(LPVOID lpData) {while (TRUE) {// 初始化内存UseGoods("外挂线程:222");Sleep(1 * 1000);}
      }// 游戏主线程
      void CDataExceptionTestDlg::OnBnClickedButton1()
      {// TODO: 在此添加控件通知处理程序代码CreateThread(NULL, NULL, GameMainThreadProc, NULL, 0, NULL);
      }// 外挂线程
      void CDataExceptionTestDlg::OnBnClickedButton2()
      {// TODO: 在此添加控件通知处理程序代码CreateThread(NULL, NULL, GameMyThreadProc, NULL, 0, NULL);
      }void CDataExceptionTestDlg::OnBnClickedOk()
      {// TODO: 在此添加控件通知处理程序代码CDialogEx::OnOK();
      }void CDataExceptionTestDlg::OnBnClickedButton3()
      {// TODO: 在此添加控件通知处理程序代码// 初始化临界区InitializeCriticalSection(&lpCriticalSection);
      }

将代码注入游戏的主线程

  • 关键词

    SetWindowsHooksExa UnhookWindowsHookEx CWPSTRUCT
    

定义方法

#pragma once// HookGameMainThread.h
#define MSG_USEGOODSFORNAME 1 //使用物品的消息种类// 挂载主线程
DWORD HookMainThread();// 卸载主线程
DWORD UnHookMainThread();DWORD msgUseGoodsForName(char* szpName);

实现方法

// HookGameMainThread.cpp
#include "StructGame.h"
#include "HookGameMainThread.h"HHOOK g_hhkGame;
const DWORD MyMsgCode = RegisterWindowMessageA("MyMsgCode");
// 回调函数
LRESULT CALLBACK GameWndProc(int nCode,WPARAM wParam,LPARAM lParam
) {CWPSTRUCT* lpArg = (CWPSTRUCT*)lParam;if (nCode == HC_ACTION) {if (lpArg->hwnd == GetGameWndHandle() && lpArg->message == MyMsgCode) {DbgPrintMine((char*)("消息传到	%s\r\n"), lpArg->lParam);switch (lpArg->wParam){case MSG_USEGOODSFORNAME: {TGOODSLIST_PROPERTY goods;TGOODSLIST_PROPERTY* g = goods.getData();if (g->UseGoodsForName((char*)lpArg->lParam)) {DbgPrintMine((char*)("使用 %s 成功"), lpArg->lParam);}}; break;default:break;}return 1;}}return CallNextHookEx(g_hhkGame, nCode, wParam, lParam);
}
DWORD HookMainThread() {HWND hGame = GetGameWndHandle();DWORD ndThreadId = GetWindowThreadProcessId(hGame, NULL);if (ndThreadId != 0) {// 安装钩子g_hhkGame = SetWindowsHookEx(WH_CALLWNDPROC, GameWndProc, NULL, ndThreadId);}return 1;
}DWORD UnHookMainThread() {UnhookWindowsHookEx(g_hhkGame);return 1;
}DWORD msgUseGoodsForName(char* szpName) {// 传递消息(句柄、自定义的注册消息、自定义消息类别、消息内容(字符串))SendMessageA(GetGameWndHandle(), MyMsgCode, MSG_USEGOODSFORNAME, (LPARAM)szpName);return 1;
}

调用方法

// 连接主线程
void CMainDialogWnd::OnBnClickedButton2()
{// TODO: 在此添加控件通知处理程序代码HookMainThread();
}void CMainDialogWnd::OnBnClickedButton3()
{// TODO: 在此添加控件通知处理程序代码UnHookMainThread();
}void CMainDialogWnd::OnBnClickedButton4()
{// TODO: 在此添加控件通知处理程序代码msgUseGoodsForName("金创药(小)");
}

文件结构

运行效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mS2QrNLF-1590415578767)(https://i.loli.net/2019/07/27/5d3c0b5f3718e26663.png)]

分析怪物列表

  • 分析思路:从怪物明显的属性入手:名字、血量

    1*4+427EBA0 //怪物列表基址(1-5)

    +8 种类/2E:怪物

    +354 显示血条

    +C 怪物选中参数

    +5f4 怪物血量

    +5f8 怪物等级

    +360 怪物名字

    +1060 怪物位置X

    +1068 怪物位置Y

    +3C0 怪物生命状态 0活/1死

    [0427EBA0] //角色对象指针

    +8 //角色分类31人物/2E

    +18 //角色名字

封装怪物对象属性

  • 定义基址

    // 怪物列表基址
    #define BaseMonseterList 0x427EBA4
    
  • 定义结构

    // 怪物结构
    typedef struct TMonseterObj {//+5f4 怪物血量DWORD ndHp;//+ 5f8 怪物等级DWORD ndLevel;//+ 360 怪物名字char* szMName;//+ 1060 怪物位置Xfloat flX;//+ 1068 怪物位置Yfloat flY;//+ 3C0 怪物生命状态 0活 / 1死BOOL IsDead;
    }_TMonseterObj;// 怪物列表
    #define MONSETERNUM 20
    typedef struct TMonseterList {_TMonseterObj tMonList[MONSETERNUM];// 初始化TMonseterList* getData();// 打印信息BOOL dbgPrintMsg();
    }_TMonseterList;
    
  • 实现结构方法

    TMonseterList* TMonseterList::getData()
    {DWORD ndObj = NULL;//memset(this, 0, sizeof(TMonseterList));try{for (int i = 0; i < MONSETERNUM; i++) {ndObj = *(DWORD*)(BaseMonseterList + 4 * i);if (ndObj == 0) {this->tMonList[i].ndLevel = 0;continue;}// 怪物名字this->tMonList[i].szMName = (char*)(ndObj + 0x360);// 怪物血量this->tMonList[i].ndHp = *(DWORD*)(ndObj + 0x5f4);// 怪物等级this->tMonList[i].ndLevel = *(DWORD*)(ndObj + 0x5f8);// 怪物位置Xthis->tMonList[i].flX = *(float*)(ndObj + 0x1060);// 怪物位置Ythis->tMonList[i].flY = *(float*)(ndObj + 0x1068);// 怪物生命状态this->tMonList[i].IsDead = *(BOOL*)(ndObj + 0x3c0);}}catch (...){// 处理所有的异常DbgPrintMine((char*)"读取怪物数据异常");}return this;
    }BOOL TMonseterList::dbgPrintMsg() {for (int i = 0; i < MONSETERNUM; i++) {if (tMonList[i].ndLevel == 0) {continue;}DbgPrintMine((char*)("%s,等级:%d级;血量:%d;当前位置X:%f Y:%f;生命状态:%d"),tMonList[i].szMName,tMonList[i].ndLevel,tMonList[i].ndHp,tMonList[i].flX,tMonList[i].flY,tMonList[i].IsDead);}return TRUE;
    }
    
  • 在HOOK 内定义测试方法

    #define MSG_TEST 2 // 测试使用消息// 测试怪物
    DWORD msgTest(LPVOID lpData);
    
  • 实现

    // HookGameMainThread.cpp
    #include "StructGame.h"
    #include "HookGameMainThread.h"HHOOK g_hhkGame;
    const DWORD MyMsgCode = RegisterWindowMessageA("MyMsgCode");
    // 回调函数
    LRESULT CALLBACK GameWndProc(int nCode,WPARAM wParam,LPARAM lParam
    ) {CWPSTRUCT* lpArg = (CWPSTRUCT*)lParam;if (nCode == HC_ACTION) {if (lpArg->hwnd == GetGameWndHandle() && lpArg->message == MyMsgCode) {DbgPrintMine((char*)("消息传到	%s\r\n"), lpArg->lParam);switch (lpArg->wParam){case MSG_USEGOODSFORNAME: {TGOODSLIST_PROPERTY goods;TGOODSLIST_PROPERTY* g = goods.getData();if (g->UseGoodsForName((char*)lpArg->lParam)) {DbgPrintMine((char*)("使用 %s 成功"), lpArg->lParam);}}; break;////////////////////////////////////////////////////////////////////////case MSG_TEST: {TMonseterList tMonList;TMonseterList* ptMonList = tMonList.getData();ptMonList->dbgPrintMsg();}; break;default:break;}return 1;}}return CallNextHookEx(g_hhkGame, nCode, wParam, lParam);
    }
    DWORD HookMainThread() {HWND hGame = GetGameWndHandle();DWORD ndThreadId = GetWindowThreadProcessId(hGame, NULL);if (ndThreadId != 0) {// 安装钩子g_hhkGame = SetWindowsHookEx(WH_CALLWNDPROC, GameWndProc, NULL, ndThreadId);}return 1;
    }DWORD UnHookMainThread() {UnhookWindowsHookEx(g_hhkGame);return 1;
    }DWORD msgUseGoodsForName(char* szpName) {// 传递消息(句柄、自定义的注册消息、自定义消息类别、消息内容(字符串))SendMessageA(GetGameWndHandle(), MyMsgCode, MSG_USEGOODSFORNAME, (LPARAM)szpName);return 1;
    }////////////////////////////////////////////////////////////////////////
    DWORD msgTest(LPVOID lpData)
    {SendMessageA(GetGameWndHandle(), MyMsgCode, MSG_TEST, (LPARAM)lpData);return 0;
    }
  • 控件调用

    
    void CMainDialogWnd::OnBnClickedButton5()
    {// TODO: 在此添加控件通知处理程序代码msgTest(NULL);
    }
  • 目录结构

    img

分析动作数组(攻击和打坐)

  • 思路:
    • 通过选中的对象逆向回溯出动作的数组
    • 通过动作对象访问逆向回溯到攻击CALL 附近
    • 封包断点bp WSASend
  1. 通过选中动作,利用CE 查找基址

  2. 使用OD 分析访问内存信息,得到基址

    0082D8F2    8D8CB7 3C040000 LEA ECX,DWORD PTR DS:[EDI+ESI*4+43C]
    

    动作公式:[02e3bd58]+43c+4*0

  3. 找动作的CALL

    • 使用CE 分析动作对象的调用访问

    • 得到一下信息

      // 攻击
      008530CE - 6A 01 - push 01
      008530D0 - E8 0B4AFBFF - call Client.exe+407AE0
      008530D5 - 8B 8C B7 3C040000  - mov ecx,[edi+esi*4+0000043C] <<
      008530DC - 85 C9  - test ecx,ecx
      008530DE - 74 62 - je Client.exe+453142008544B9 - 83 BF 34160000 35 - cmp dword ptr [edi+00001634],35
      008544C0 - 75 20 - jne Client.exe+4544E2
      008544C2 - 8B 84 B7 3C040000  - mov eax,[edi+esi*4+0000043C] <<
      008544C9 - 85 C0  - test eax,eax
      008544CB - 74 15 - je Client.exe+4544E2
    • 使用OD分析得动作CALL为

      mov edi, [02E3CD58]
      mov esi, 下标
      MOV EAX,DWORD PTR DS:[EDI+ESI*4+43C]
      mov ecx, [eax+0x54]
      push ecx
      CALL 007139E0

封装动作数组功能

  • 封装动作对象
  • 封装动作对象列表
  • 封装使用对象功能函数

封装

  1. 封装基址

    // 人物动作使用的CALL 的基址
    #define BaseActionCall 0x00713970
    
  2. 封装结构

    // 动作对象的结构
    typedef struct TActionObj {// 对象名字char* szpName;// 调用CALL 的参数DWORD ndActionID;}_TActionObj;// 动作对象数组
    #define ActionNum 18
    typedef struct TCActionList {// 定义动作数组_TActionObj tList[ActionNum];// 初始化TCActionList* getData();// 打印信息BOOL TestActionMsg();// 使用动作通过下标BOOL UseActionByIndex(DWORD ndIndex);// 使用动作通过名字BOOL UseActionByName(char* szpName);}_TCActionList;
    
  3. 实现结构方法

TCActionList* TCActionList::getData()
{//dc [[02e3bd58]+ 43c + 4 * 0] + 64//+ 64 动作名字//[[02e3bd58]+ 43c + 4 * 0] + 54//+ 54 调用CALL参数DWORD ndFirstObj = 0;DWORD ndObj;try {ndFirstObj = (*(DWORD*)(BaseActionList))+0x43C;for (int i = 0; i < ActionNum; i++) {ndObj = *(DWORD*)(ndFirstObj + 4 * i);if (ndObj == NULL) {tList[i].ndActionID = 0;continue;}tList[i].szpName = (char*)(ndObj + 0x64);tList[i].ndActionID = *(DWORD*)(ndObj + 0x54);}}catch (...) {DbgPrintMine((char*)("内存读取异常"));}return this;
}BOOL TCActionList::TestActionMsg()
{for (int i = 0; i < ActionNum; i++) {if (tList[i].ndActionID == 0) {continue;}DbgPrintMine((char*)("动作名:%s, 动作ID:%X"),tList[i].szpName,tList[i].ndActionID);}return TRUE;
}DWORD getObjByIndex(char* szpName) {TCActionList tList;TCActionList* ptList = tList.getData();for(int i = 0; i < ActionNum; i++) {if (strcmp(szpName, ptList->tList[i].szpName) == 0) {return i;}}return -1;
}BOOL UseAction(DWORD ndIndex) {TCActionList tList;TCActionList* ptList = tList.getData();DWORD ndPrarm = ptList->tList[ndIndex].ndActionID;try {__asm {mov ecx, ndPrarmpush ecxmov eax, BaseActionCallcall eax}}catch (...) {DbgPrintMine((char*)("动作使用失败"));return FALSE;}return TRUE;
}BOOL TCActionList::UseActionByIndex(DWORD ndIndex)
{if (UseAction(ndIndex)) {MessageBeep(0);return TRUE;}return FALSE;
}BOOL TCActionList::UseActionByName(char* szpName)
{DWORD ndIndex = getObjByIndex(szpName);if (ndIndex != -1) {if (UseAction(ndIndex)) {MessageBeep(0);return TRUE;}}return FALSE;
}
  1. 添加消息类型

    #define MSG_ACTIONTEST 3 //测试动作
    
  2. 在主线程内调用结构体方法

    case MSG_ACTIONTEST: {TCActionList* ptLIst = tList.getData();ptLIst->TestActionMsg();//ptLIst->UseActionByIndex(1);ptLIst->UseActionByName((char*)("攻击"));}; break;
    
  3. 发送消息到主线程

    DWORD testActionMsg(LPVOID lpData) {SendMessageA(GetGameWndHandle(), MyMsgCode, MSG_ACTIONTEST, (LPARAM)lpData);return 0;
    }
    
  4. 绑定控件,执行方法

    void CMainDialogWnd::OnBnClickedButton6()
    {// TODO: 在此添加控件通知处理程序代码testActionMsg(NULL);
    }
    
  • 文件结构

    img

选怪功能实现

  • 实现怪物选中
  • 可能情况:
    • 选怪变量被赋值
    • 怪物是否被选中的属性

选怪功能相关地址

  • 玩家:

    [2E63A24] //存放的玩家对象的地址

    +3428 玩家是否被选中

  • 怪物:

    [2E63A24]+1A64

    选中怪物时,传入怪物的选中ID

    没选中怪物时,值为0xFFFF

选怪功能的封装

计算怪物与玩家的距离

自动打怪函数封装

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Nowcoder java-变态跳台阶

    Nowcoder java-变态跳台阶题目思路1.青蛙角度思路2.台阶角度代码 题目 (题目来自牛客网站) 思路1.青蛙角度 1.青蛙角度 关于本题,前提是n个台阶会有一次n阶的跳法。分析如下:f(n)表示n个台阶有多少种跳法 f(1) = 1 f(2) = f(2-1) + f(2-2) //f(2-1) 表示2阶一次跳1…...

    2024/4/16 20:34:13
  2. elasticSearch简介及安装(内含linux下的es+head+kibana)

    elasticsearch的简介 什么是es(elasticSearch)? 我的理解es是一个数据库或者成为中间件,是一个用RESTful进行增删改查的数据库;这种数据库多是用于搜索。而这种搜索有别于关系型数据库的搜索。------------倒排索引搜索 关于倒排索引可以这么理解:我们以前是通过歌名找歌…...

    2024/4/29 3:35:43
  3. Filter 拦截器 过滤器

    Filter 1、过滤器,由servlet容器调用,用来拦截以及处理请求和响应 2、其本身不能生成请求和响应对象,但可以对请求和响应对象进行检查和修改 3、过滤器介于客户端与Servlet/JSP等相关的资源之间,对于与过滤器关联的Servlet来说,过滤器可以在Servlet被调用之前检查并且修改…...

    2024/4/20 10:05:59
  4. 2. 想用cmake,你就老老实实用Linux系统,别在windows瞎用cmake,windows上有大把更方便的编译器,何苦呢,骚年

    有时间,把这个博客拆分成一个个小问题出来,先这样全部写[2020-5-25]一 问题描述 无知小伙想在windows上学习CJSON,而后DEV C++不管用。继小伙在Ubuntu上成功用cmake编译运行后,贪心的小伙想在windows上也要用cmake去实现,小伙因此学了vscode+cmake+mingw实现了在vscode上编…...

    2024/4/16 20:34:01
  5. Android Studio实现简单的百度地图定位

    **Android Studio实现简单的百度地图定位**项目前期准备可观看以下的视频回放: 腾讯课堂知识回放 代码实现: DemoApplication.java package com.example.lk.baidumapapplication;import android.app.Application;import com.baidu.mapapi.CoordType; import com.baidu.mapapi.S…...

    2024/4/15 7:17:14
  6. Centos下安装IDEA

    1 去Intellij官网,下载idea 本文下载的idea为ideaIC-2018.3.3.tar.gz 官网地址为: https://download.jetbrains.com/idea/2、安装 在需要安装软件的位置下面新建一个文件夹$mkdir /home/azprogramm/idea将下载的安装包拷贝至此目录下并解压$tar -zxvf ideaIC-2018.3.3.tar…...

    2024/4/24 7:22:49
  7. Mysql5.7性能提升一百倍调优宝典

    全文中一共有常用的(事实上你如果花1-2周阅读、理解、自己动手设一下后是需要这么多参数的)76个参数,笔者把近10年里3个亿万级项目的数据库调优用此篇浓缩到了可能读者只需要2周时间就可以掌握,同时我是按照:每一个参数干吗?在某些典型硬件配置下的db上参数该设多少?设会…...

    2024/4/24 7:22:48
  8. Hyperledger Fabric 2.0新特性

    参考资料:官方文档 智能合约的去中心化治理Fabric v2.0 引入了智能合约的去中心化治理,新的Fabric 链码生命周期支持多个组织在链码和账本交互之前协商链码的参数,例如链码背书策略。和以前的生命周期相比,新的模式有几个改进:多个组织必须认同链码参数: 在 Fabric 1.x 版本…...

    2024/4/24 7:22:54
  9. Linux常用命令总结(最新版)

    命令总结:ip address show/ip a 检查网络配置ping www.biaidu.com 测试网络联通性nmtui 图形界面修改网卡地址信息exit 注销shutdown 关机命令 shutdown -h 5 指定关机时间(推荐) shutdown -r 5 重启关机时间(推荐) shutdown -…...

    2024/5/2 23:34:46
  10. Redis学习7——与spring结合

    一、先加入关于Redis的依赖 Spring Boot也会为其提供stater,然后允许我们通过配置文件application.properties进行配置。 对映的Maven中依赖: 引入spring-boot-starter-data-redis <dependency><groupId>org.springframework.boot</groupId><artifactId&…...

    2024/4/24 7:22:46
  11. 蓝桥杯 PREV-43 拉马车(试题解析)

    试题 历届试题 拉马车提交此题 评测记录 资源限制时间限制:1.0s 内存限制:256.0MB问题描述小的时候,你玩过纸牌游戏吗?有一种叫做“拉马车”的游戏,规则很简单,却很吸引小朋友。其规则简述如下:假设参加游戏的小朋友是A和B,游戏开始的时候,他们得到的随机的纸牌序…...

    2024/4/24 7:22:44
  12. 防止回车时提交表单

    如何防止回车(Enter)键提交表单,其实很简单,就一句话。οnkeydοwn="if(event.keyCode==13)return false;"把这句写在from标签里面就好了。<form name="form1" action="action/soft_add_action.php" enctype="multipart/form-data&q…...

    2024/4/24 7:22:43
  13. web笔记

    一.HTML是什么超文本标记语言二 . 五大浏览器Ie(Trident) 火狐(Gecko) 苹果safari(Webkit) 谷歌(Blink) opera(Presto)三.Web标准的好处让web的前景发展更广阔更容易被搜索引擎搜索内容能被更广泛的设备访问降低网站流量费用使网站更易于维护提高页面浏览速度四.W…...

    2024/4/24 7:22:42
  14. 爬虫-find_all()和find()方法

    1. find_all()和find() find_all()⽅法以列表形式返回所有的搜索到的标签数据。 find()⽅法返回搜索到的第⼀条数据 find_all(self, name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs) name : tag 名称 attrs :标签的属性 recursive : 是否递归 text : …...

    2024/4/24 7:22:43
  15. html的认识和标签的了解

    常用浏览器:火狐,谷歌,safari,opera,IE浏览器的内核:Trident(IE内核),Gecko(火狐),webkit(苹果safari),Chromium/Blink(谷歌),Presto(Opera)网页标准:web前端的维护,前景广阔,引擎搜索,流量,浏览速度,降低流量费用(赚钱) web的构成:xml。xhtml(h…...

    2024/5/2 17:11:47
  16. GPUImage图像处理源码精讲(一) -- 滤镜效果

    GPUImage 在阅读Rac,Masonry,AFNetworking源码后,我们稍作放松,来看另一个经典常用的第三方框架GPUImage,利用GPUImage对图片视频进行滤镜效果处理和优化。 示例效果 下面图片是通过GPUImage添加褐色渲染生成的照片,这一操作和手机上使用的滤镜软件别无差别。GPUImage官方…...

    2024/4/24 7:22:40
  17. 什么是NUMA

    什么是NUMA Non-Uniform Memory Access (NUMA) refers to multiprocessor systems whose memory is divided into multiple memory nodes. The access time of a memory node depends on the relative locations of the accessing CPU and the accessed node. (This contrasts …...

    2024/4/23 19:18:35
  18. WireMock.NET如何帮助进行.NET Core应用程序的集成测试

    目录介绍背景使用代码兴趣点许多应用程序仅使用xUnit进行了单元测试,而未进行集成测试。.NET Core提供了进行集成测试的好方法。您的测试将比单元测试更加实际,因为将仅模拟外部依赖关系而不会模拟内部依赖关系。WireMock.NET提供了执行此操作的方法。从GitHub下载完整的源代…...

    2024/4/16 20:34:13
  19. Lua学习随感之一Lua中实现Unity的Update方法

    前言 这里写一个Lua端Update,FixedUpdate,LateUpdate方法。 代码我们需要在C#端写一个Update类,用来回调Lua的Update方法using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua;[CSharpCallLua] public class LuaUpdate…...

    2024/4/15 7:17:28
  20. 通信工程的岗位有哪些?

    通信行业的岗位:网优、工程督导、工程设计、技术支持、设备生产、传输工程师、运维工程师、监控网管、施工人员、调测工程师、软件开发等。 (1)网络优化是指通过各种硬件或软件技术使网络性能达到我们需要的最佳平衡点!网络优化也是SEO。网络优化主要分为设备及服务两个方面…...

    2024/4/16 20:34:37

最新文章

  1. 【Linux的文件篇章 - 磁盘文件】

    Linux学习笔记---012 Linux之进程程序替换理解1、磁盘文件1.1、文件如何存取的问题1.2、了解磁盘的存储结构1.3、如何找到指定位置的扇区&#xff1f;1.4、对磁盘的存储进行逻辑抽象(了解OS对磁盘这样的硬件设备的抽象与管理) 2、磁盘级文件系统2.1、Linux文件系统特定2.2、文件…...

    2024/5/3 0:06:39
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. nginx配置证书和私钥进行SSL通信验证

    文章目录 一、背景1.1 秘钥和证书是两个东西吗&#xff1f;1.2 介绍下nginx配置文件中参数ssl_certificate和ssl_certificate_key1.3介绍下nginx支持的证书类型1.4 目前nginx支持哪种证书格式&#xff1f;1.5 nginx修改配置文件目前方式也会有所不同1.6 介绍下不通格式的证书哪…...

    2024/5/1 3:19:57
  4. audio_video_img图片音视频异步可视化加载

    最近在做即时消息&#xff0c;消息类型除了文字还有音频、视频、图片展示&#xff0c;如果消息很多&#xff0c;在切换聊天框时&#xff0c;会有明显卡顿&#xff0c;后续做了懒加载&#xff0c;方案是只加载用户能看到的资源&#xff0c;看不到的先不加载&#xff1b; LazyAud…...

    2024/5/2 22:59:28
  5. 浅聊什么是Redis?

    需求&#xff1a;MySQL面临大量的查询&#xff0c;即读写操作&#xff0c;因此类比CPU&#xff0c;给数据加缓存&#xff0c;Redis诞生。应用程序从MySQL查询的数据&#xff0c;在Redis设置缓存&#xff08;记录在内存中&#xff0c;无需IO操作&#xff09;&#xff0c;后再需要…...

    2024/5/2 22:15:36
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/2 16:16:39
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/2 9:28:15
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/2 15:04:34
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/2 9:07:46
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57