92.网络游戏逆向分析与漏洞攻防-游戏技能系统分析-利用哈希表实现快速读取文本内容

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

如果看不懂、不知道现在做的什么,那就跟着做完看效果,代码看不懂是正常的,只要会抄就行,抄着抄着就能懂了

内容参考于:易道云信息技术研究院

上一个内容:91.加载游戏语言文件到内存

码云版本号:aafa72010a0c9ffb42274c1c2ff3a61e627eb49f

代码下载地址,在 titan 目录下,文件名为:titan-利用哈希表实现快速读取文本内容.zip

链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg

提取码:q9n5

--来自百度网盘超级会员V4的分享

HOOK引擎,文件名为:黑兔sdk升级版.zip

链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw

提取码:78h8

--来自百度网盘超级会员V4的分享

以 91.加载游戏语言文件到内存 它的代码为基础进行修改

现在已经把游戏里的语言文件写到了本次磁盘里,并且把这个文件加载到了我们程序的内存中

找有冲突的中文

下图红框里是 textDatas 变量的地址,也就是从磁盘文件中加载的语言包的地址

然后打开x96dbg,然后附加到游戏

鼠标单击下图红框位置,也就是x96dbg的内存窗口位置

然后ctrl+g,然后输入,textDatas 变量的地址

如下图,在7CCFF27C位置鼠标右击选择在内存窗口中转到知道DWORD

然后就来到了语言包的内存区域,现在还没有赋值所以全是0

然后回到游戏点击确定,如下图红框

点击完确定就会有值了

这个原因是,弹框的代码是在解析语言包之前

然后第一个不是-1,它就是存在哈希冲突

然后找它的链表,上图是链表第一个数据,通过下图得出的589A8740是链表的第二个数据,现在要找链表的最后一个数据,找最后一个数据的愿意是为了测试我们通过磁盘文件加载的语言包是否可以用,然后DAC*30,这个30是十六进制的,30的十进制是48,这个48是 TextTable 结构的大小

TextTable 结构的大小也就是下图红框位置

然后鼠标单击x96dbg的内存窗口,然后按ctrl+g,然后输入地址,然后点确定转到

然后发现它还不是-1,所以它不是最后一个数据

继续找

看到它还不是-1

继续

然后就找到-1了

它的中文是,水系咏唱法术

0x58D6F9D0位置字符串的效果图

然后发现个事情0x7CCFF27C这个位置的值是0x5897B020,但是x96dbg跳过去之后不是了,如下图,是刚开始的地方,x96dbg给我们跳到了0x5897B050位置了,但是找哈希冲突的值也还是上方那样的找发,图都截完了才发现x96dbg给跳错了

TextManger.cpp文件的修改:修改了 LoadTextData函数、ReadTextById函数

#include "pch.h"
#include "TextManger.h"

unsigned TextManger::ReadTextProc = 0x10295FB0;
const wchar_t TextManger::NullText[2]{};

bool TextManger::CreateTextDat(const char* _filename)
{
	if (!textTable) {
		return false;
	}
	std::ofstream out(_filename, std::ios::out|std::ios::binary);

	if (out.bad())return false;
	out.write((char*)&hashCount, sizeof(hashCount));
	for (int i = 0; i < hashCount; i++) {
		// 游戏中的中文表结构是 中文名英文id 这样的
		int lenId = strlen(textTable[i]->TxtId) + 1;
		// 宽字节一个字是2字节,wcslen函数返回值是字的个数
		int lenTxt = wcslen(textTable[i]->Txt) + 1;
		lenTxt = lenTxt * 2;
		out.write(textTable[i]->TxtId, lenId);
		out.write((char*)textTable[i]->Txt, lenTxt);
	}
	out.close();
	return true;
}

bool TextManger::LoadTextData(const char* _filename)
{
	CString txt;
	if (textDatas)return false;
	std::ifstream file(_filename, std::ios::in | std::ios::binary|std::ios::ate);

	if(file.bad()) {
		return false;
	}
	unsigned buffSize = file.tellg();
	TextBuff = new char[buffSize];
	file.seekg(std::ios::beg);
	file.read(TextBuff, buffSize);
	// textTable = new PTextTable[Count[0]];
	textDatas = new TextTable[Count[0]];
	txt.Format(L"%X", &textDatas);
	AfxMessageBox(txt);
	char* buffStart = TextBuff + 4;
	char* buffEnd = buffStart + buffSize;
	int icount = 0;
	while(buffStart < buffEnd){// 读取语言文件的数据到 textDatas 变量里
		int lenId = strlen(buffStart) + 1;
		memcpy(textDatas[icount].TxtId, buffStart, 0x24);
		buffStart = buffStart + lenId;
		int lenTxt = wcslen((wchar_t*)buffStart) + 1;
		lenTxt = lenTxt * 2;
		textDatas[icount].Txt = (wchar_t*)buffStart;
		buffStart = buffStart + lenTxt;
		icount++;
	}

	hashCount = Count[0];
	HashIndexTable = new unsigned[hashCount];
	memset(HashIndexTable, 0xFF, hashCount * sizeof(unsigned));

	for (int i = 0; i < Count[0]; i++) {// 给 textDatas 变量添加哈希算法索引(哈希表存放 textDatas的下标)
		unsigned hash = Hashcode(textDatas[i].TxtId);
		hash = hash % (hashCount + 1);
		if (HashIndexTable[hash] == -1) {
			HashIndexTable[hash] = i;
		}
		else {
			PTextTable nullTable = GetNullText(&textDatas[HashIndexTable[hash]]);
			nullTable->next = i;
		}
	}

	return false;
}

const wchar_t* TextManger::ReadTextById(const char* _id)
{
	// unsigned callProc = 0x10295FB0;

	if (textTable) {
		int index;
		_asm {
			push ebx
			mov ebx, this
			push _id
			call ReadTextProc
			mov index, eax
			pop ebx
		}
		if (index < 0)return NullText;
		PTextTable* _table = textTable;

		return (wchar_t*)_table[index]->Txt;
	}
	else {
		unsigned hash = Hashcode(_id);
		hash = hash % (hashCount + 1);
		unsigned index = HashIndexTable[hash];
		if (index > hashCount) {// index的值如果是-1那么它肯定比hashCount大
			return NullText;
		}
		while (strcmp(textDatas[index].TxtId, _id)) {
			index = textDatas[index].next;
			if (index > hashCount)return NullText;
		}
		return textDatas[index].Txt;
	}
}

unsigned TextManger::Hashcode(const char* id)
{
	unsigned hash = 0;
	for (int i = 0; id[i]; i++)
	{
		hash = hash * 131 + id[i];
	}
	return hash;
}

PTextTable TextManger::GetNullText(PTextTable _table)
{
	while (_table->next != -1) {// 从链表中找出最后一个(next的值是-1的)
		_table = &textDatas[_table->next];
	}
	return _table;
}

TextManger.h文件的修改:修改了 TextTable结构体

#pragma once
#include <iostream>
#include <fstream>

/*
03E1B73B | 68 58120304              | push fxgamelogic.4031258         | 4031258:"gui"
03E1B740 | E8 7BEF0F00              | call fxgamelogic.3F1A6C0         |
03E1B745 | 83C4 04                  | add esp,4                        |
03E1B748 | 85C0                     | test eax,eax                     |
03E1B74A | 0F84 10090000            | je fxgamelogic.3E1C060           |
03E1B750 | 68 4C120304              | push fxgamelogic.403124C         | 403124C:"TextManager"
03E1B755 | 50                       | push eax                         |
03E1B756 | 8D4C24 64                | lea ecx,dword ptr ss:[esp+64]    |
03E1B75A | 51                       | push ecx                         |
03E1B75B | E8 00091000              | call fxgamelogic.3F1C060         |
03E1B760 | 8D5424 68                | lea edx,dword ptr ss:[esp+68]    |
03E1B764 | 52                       | push edx                         |
03E1B765 | E8 16EF0F00              | call fxgamelogic.3F1A680         | 111111111111
03E1B76A | 83C4 10                  | add esp,10                       |
03E1B76D | 85C0                     | test eax,eax                     |
03E1B76F | 894424 14                | mov dword ptr ss:[esp+14],eax    | [esp+14]:CD3DDDIDX10_DrawIndexedPrimitive+113
*/
// 游戏中的中文表结构是 中文名英文id 这样的
typedef class TextTable {
public:
	int next = ((int)0xFFFFFFFF);
	int un = sizeof(TextTable);
	wchar_t* Txt;// 中文
	char TxtId[0x24];// 中文对应的英文id
}*PTextTable;

typedef class TextManger
{
public:
	static unsigned ReadTextProc;
	static const wchar_t NullText[2];
private:
	//int un[0x20];// 0x20 * 0x4 = 0x80
	int un[0x1E];
	union {
		char* TextBuff;
		unsigned* Count;
	};
	PTextTable textDatas = nullptr; // 中文结构
public:
	PTextTable* textTable = nullptr; // 暂时无用
private:
	int un1;
public:
	unsigned hashCount;
	unsigned* HashIndexTable = nullptr; // 哈希表
public:
	bool CreateTextDat(const char* filename); // 导出语言包
	bool LoadTextData(const char* _filename); // 加载 CreateTextDat函数写出的文件
	const wchar_t* ReadTextById(const char* _id); // 根据id获取中文名
	unsigned Hashcode(const char* id);// 哈希函数
	// 获取一个未使用的中文与对应id结构,用与存放从文件中读取的中文与对应id
	PTextTable GetNullText(PTextTable _table);
}*PTextManger;


CUIWnd_0.cpp文件的修改:修改了 OnBnClickedButton2函数

// CUIWnd_0.cpp: 实现文件
//

#include "pch.h"
#include "htdMfcDll.h"
#include "CUIWnd_0.h"
#include "afxdialogex.h"
#include "extern_all.h"
#include "GameOBJECTDef.h"

// CUIWnd_0 对话框
float _xNext = 0.0f;
float _yNext = 0.0f;
void _stdcall loops(HWND, UINT, UINT_PTR, DWORD) {
	PAIM aim = Client->GetAimByName(L"r");
	if (aim == nullptr) {
		return;
	}
	//AfxMessageBox(aim->Name);
	float xDis = fabs(Client->Player.x - aim->x);
	float hDis = fabs(Client->Player.h - aim->h);
	float yDis = fabs(Client->Player.y - aim->y);

	float xNext, yNext, thisx, thisy;

	int v[2]{ -1, 1 };

	if (xDis > 12) {
		// 强制修改角色x坐标的值
		thisx = Client->Player.x;
		Client->Player.x = Client->Player.x + 6 * v[Client->Player.x < aim->x];
		xNext = Client->Player.x;
	}
	else {
		xNext = aim->x;
	}
	if (yDis > 12) {
		// 强制修改角色y坐标的值
		thisy = Client->Player.y;
		Client->Player.y = Client->Player.y + 6 * v[Client->Player.y < aim->y];
		yNext = Client->Player.y;
	}else{
		yNext = aim->y;
	}
	if ((xDis < 2)&&(hDis < 2)&&(yDis < 2)) {
		Client->MoveStop(aim->x, aim->h, aim->y, 0.0f);
	}
	else {
		Client->MoveWalk(Client->Player.x,aim->h, Client->Player.x, 0.0f, 0.0f, xNext, yNext);
	}
}

IMPLEMENT_DYNAMIC(CUIWnd_0, CDialogEx)

CUIWnd_0::CUIWnd_0(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_PAGE_0, pParent)
{

}

CUIWnd_0::~CUIWnd_0()
{
}

void CUIWnd_0::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CUIWnd_0, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON1, &CUIWnd_0::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &CUIWnd_0::OnBnClickedButton2)
END_MESSAGE_MAP()


// CUIWnd_0 消息处理程序


void CUIWnd_0::OnBnClickedButton1()
{
	// 发送坠落数据包
	//Client->Fall();
	
	 设置移动速度
	float Speed = 30.0;
	Client->SetProperty(Client->Player.lId, INDEX_MoveSpeed, &Speed);
	/*
	// 修改血量
	int HP = 10000000;
	Client->SetProperty(Client->Player.lId, INDEX_HP, &HP);*/
	/*CString txt;
	txt.Format(L"通过AIM类获取角色信息 名字:%s,x坐标:%f", Client->Player.Name, Client->Player.x);
	AfxMessageBox(txt);*/
	// Client->HeartBeep();
	// Client->TalkTo(L"r", L"打架吗?");
	// Client->Talk(L"[欢迎来到麟科思]");
	// Client->SelectRole(L"今晚打老虎");
	/*Client->CreateRole(L"am4", 1.0, 2.0, 4.0, 8.0, "gui\BG_team\TeamRole\Teamrole_zq_humF_001.PNG",
		"Face,0;Hat,0;Eyes,0;Beard,0;Ears,0;Tail,0;Finger,0;Cloth,0;Pants,0;Gloves,0;Shoes,0;Trait,0;HairColor,0;SkinColor,0;SkinMtl,0;Tattoo,0;TattooColor,16777215;",
		"", 0.0);*/
	//Client->SelectCamp("xuanrenZQ");
	//Client->StartCreateRole();
	//Client->DelRole(L"ranzhi11111");
	/*
	char buff[] = {
		0xA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x4, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 00 ,0x00,
		0x00, 0x07, 0x0E, 0x00, 0x00, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x31, 0x00, 0x32 ,0x00,
		0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	};
	WinSock->OnSend(buff, sizeof(buff));
	*/
	/*char buff[] = {
		0x27, 0x46, 0x92, 0x02, 0x00, 0x00, 0x89, 0x02, 0x00, 0x00, 0x06, 0x00, 0x06, 0x05, 
		0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x74, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x07, 
		0x0A, 0x00, 0x00, 0x00, 0x34, 0x00, 0x33, 0x00, 0x39, 0x00, 0x39, 0x00, 0x00, 0x00, 
		0x07, 0x5A, 0x02, 0x00, 0x00, 0x31, 0x00, 0x32, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 
		0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 
		0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 
		0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 
		0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 
		0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 
		0x00, 0x32, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 
		0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 
		0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 
		0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 
		0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 
		0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
		0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x35, 
		0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 
		0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 
		0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 
		0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 
		0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 
		0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x34, 
		0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 
		0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 
		0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 
		0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 
		0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 
		0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36,
		0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 
		0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 
		0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x37, 
		0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 
		0x38, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
	};
	WinSock->OnRecv(buff, sizeof(buff));*/
}

TextManger txtMangerMain;
void CUIWnd_0::OnBnClickedButton2()
{
	// 根据语言表获取文字
	//CString txt = txtManger->ReadTextById("npc_GRZJ_0001");// PGameProc->GetTextName("npc_GRZJ_0001");
	//AfxMessageBox(txt);
	//txtManger->CreateTextDat("F:\\语言包.txt");
	// 读取导出到本地的语言包
	txtMangerMain.LoadTextData("F:\\语言包.txt");
	// CString txt = txtMangerMain.ReadTextById("npc_GRZJ_0001");// npc_GRZJ_0001没有哈希冲突
	/* 
		Hui_event_3_1有哈希冲突,通过打印 textDatas 变量的内存地址
		去x96db找的(第一个就冲突了,ui_event_3_1是第一个哈希表里的链表的最后一个)
		如果第一个没有冲突,那就找一个 next 不是 -1 的,不是-1说明是链表,然后找链表最后一个就可以了
	*/

	CString txt = txtMangerMain.ReadTextById("ui_event_3_1");
	AfxMessageBox(txt);
	txt = txtMangerMain.ReadTextById("desc_Item_A550001_01_2");
	AfxMessageBox(txt);
	// 瞬移
	//float decX = 3843.776123f;
	//float decH = 11.731983f;
	//float decY = -2005.533813f;
	//float face = 0.0f;
	//Client->Teleport(decX, decH, decY, face);
	//PAIM aim = Client->GetAimByName(L"r");
	//if (aim == nullptr) {
	//	return;
	//}
	//Client->Teleport(aim->x, aim->h, aim->y, aim->face);
	// 修正坐标
	/*PAIM aim = Client->GetAimByName(L"r");
	if (aim == nullptr) {
		return;
	}
	Client->SetCoord(Client->Player.lId, aim->x, aim->h, aim->y, aim->face);*/
	// 面向
	// Client->FaceTo(L"r");
	// 飞天
	// Client->HideMode = true;
	// 遁地
	//Client->MoveStop(Client->Player.x, Client->Player.h - 5, Client->Player.y, 0.0f);
	// 跟随
	// ::SetTimer(m_hWnd, 0x1000, 2000, loops);
	// 
	// Client->Backtoroles();
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/636155.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

k8s dashboard安装

本案例&#xff0c;k8s版本为v1.22.17&#xff0c;所以安装v2.7.0版本的dashboard 1、下载dashboard的yaml文件 curl -O https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml 2、修改recommended.yaml文件 修改定义的Service&…

java版本spring cloud-spring boot高效知识付费SaaS平台的架构与功能模块设计

知识付费平台是一种快速发展的在线教育模式&#xff0c;它以满足用户需求为核心&#xff0c;提供便捷高效的学习渠道。该平台汇聚了各类专业知识&#xff0c;覆盖职业技能、生活兴趣和人文社科等多个领域&#xff0c;满足不同用户的学习需求。同时&#xff0c;平台还提供视频播…

通过 PW6606 快充电压诱骗芯片,了解 USB-A 与 USB-C 快充协议

充电器一般分两种&#xff1a; 1&#xff0c; A 口充电器&#xff0c;就是我们常见的 USB 口&#xff0c;如下图&#xff0c;这种通用快充协议叫&#xff1a; QC3.0,QC2.0 快充&#xff0c;是属于快充刚开始的充电协议&#xff0c;支持 5V,9V,12V 和 20V 电压输出充电器&#x…

聚观早报 | 拼多多第一季度营收;苹果2024款彩虹表带上市

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 5月24日消息 拼多多第一季度营收 苹果2024款彩虹表带上市 小米汽车智驾将提速 iPhone 16 Pro Max将用最大屏幕 …

20240520解决在Ubuntu20.04下编译RK3588的Android12的SDK出现C2_GIT_BUILD_VERSION未定义的问题

20240520解决在Ubuntu20.04下编译RK3588的Android12的SDK出现C2_GIT_BUILD_VERSION未定义的问题 2024/5/20 20:19 缘起&#xff1a;通过./repo/repo/repo sync -l得到的SDK正常&#xff0c;但是解压缩之后的SDK却出错了&#xff01; 通过grep很容易发现有三个地方有&#xff0c…

Jenkins 构建 Maven 项目:项目和服务器在一起的情况

bash.sh内容 #!/bin/bash#删除历史数据 rm -rf ruoyi-admin.jar# appname$1 appnamevideo.xxxxx.com #获取传入的参数 echo "arg:$appname"#获取正在运行的jar包pid # pidps -ef | grep $1 | grep java -jar | awk {printf $2} pidps -ef | grep $appname | grep ja…

【加密与解密(第四版)】第十三章笔记

第十三章 HOOK技术 13.1 Hook概述 IAT HOOK&#xff08;改地址&#xff09; BOOL IAT_InstallHook(){BOOL bResult FALSE ;HMODULE hCurExe GetModuleHandle(NULL);PULONG_PTR pt ;ULONG_PTR OrginalAddr;bResult InstallModuleIATHook(hCurExe,"user32.dll",&qu…

将联表查询到的数据按1000一批次存入数据库-模板

idea模板&#xff1a; /*** ${Shitilei}信息 服务层实现。** author admin*/ Service RequiredArgsConstructor public class Operate${Shitilei}Service {private final ${Shitilei}Mapper ${shitilei}Mapper;private final RegionUtil util;/*** ${shitilei}表* return 操作结…

解决Ubuntu无法使用root登录的问题

1、登录普通用户 2、使用vi编辑器打开/etc/pam.d/gdm-autologin并注释掉auth required pam_succeed_if.so user ! root quiet_success 3、使用vi编辑器打开/etc/pam.d/gdm-password并注释掉auth required pam_succeed_if.so user ! root quiet_success 4、注销用户重新用roo…

【网络协议】【OSI】一次HTTP请求OSI工作过程详细解析

目录 1. 一次HTTP请求OSI工作过程 1.1 应用层&#xff08;第7层&#xff09; 1.2 表示层&#xff08;第6层&#xff09; 1.3 会话层&#xff08;第5层&#xff09; 1.4 传输层&#xff08;第4层&#xff09; 1.5 网络层&#xff08;第3层&#xff09; 1.6 数据链路层&am…

Z缓冲技术在AI去衣中的关键角色

引言&#xff1a; 人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;为图像处理领域带来了革命性的变化。其中&#xff0c;AI去衣技术作为一种新兴的应用&#xff0c;引起了广泛关注。它不仅在多媒体内容的编辑、虚拟现实和增强现实等领域具有重要的应用价值&…

Java八大类型详解

整数类型 (4种) 整数的类型 类型占用内存空间范围byte [字节]1字节-128 ~ 127存放的范围是>二进制short [短整型]2字节 -(2⁵) ~ 2⁵-1 -32768 ~ 32767 int [整形]4字节 -2 ~ 2-1 -2147483648 - 2147483647 long [长整形]8字节-2⁶ ~ 2⁶-1 整数类型的使用细节 1. Java个…

el-table 划入划出方法

<template><div><el-table :data"tableData" style"width: 100%" cell-mouse-enter"handleMouseEnter" cell-mouse-leave"handleMouseLeave"><el-table-column prop"ddd" label"日期2" widt…

Java 数组的基本使用

目录 含义语法格式语句特点数组的长度数组的元素打印数组显示数组数组的复制扩展示例【12】&#xff1a; 含义 数组&#xff08;array&#xff09;是一种最简单的复合数据类型&#xff0c;它是有序数据的集合&#xff0c;数组中的每个元素具有相同的数据类型&#xff0c;可以用…

Mysql基础教程(06):NOT IN

数据准备 首先创建一个数据库educational_manage&#xff0c;记住字符集和排序规则如下选择&#xff1a; 接着创建表和数据&#xff0c;具体的sql代码如下&#xff1a; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure f…

JavaScript-隐式转换和显式转换

为什么需要类型转换&#xff1f; 因为JavaScript是弱类型声明&#xff0c;在没赋值前是不知道数据的类型的&#xff0c;只有赋值了才知道&#xff0c;表单和prompt获取的数据都是字符串型&#xff0c;此时就不能直接的简单加减法运算 所以需要转换数据类型 隐式转换 某些运算符…

Xcode=> 安装 simulator

XCode xcode中下载 simulator 点击加号➕&#xff0c;选择对应的版本&#xff0c;即可下载 下载完成&#xff1a; 其他下载办法 因为使用上述下载&#xff0c;会经常性的出现断开&#xff0c;再次下载又是从头开始&#xff0c;太费时费力。下面使用下载地址&#xff0c;然后用…

仓库管理WMS软件(Warehouse Management Software)百科解析

一、什么是仓库管理软件&#xff08;WMS&#xff09;&#xff1f; 仓库管理软件&#xff08;WMS&#xff09;全称Warehouse Management System&#xff0c;是一种专门用于仓库作业流程优化和库存控制的软件系统。它通过先进的自动识别与数据采集技术&#xff0c;实现对仓库货物…

人工智能(Educoder)-- 机器学习 -- 神经网络(初级)

第一关 注&#xff1a; 神经网络的起源和应用 起源&#xff1a;神经网络最早由心理学家和神经学家开创&#xff0c;目的是模拟生物神经系统对真实世界物体的交互反应。应用&#xff1a;现代神经网络用于分类&#xff08;如图像识别、文本分类&#xff09;和数值预测&#xff08…

全球手游4月战报,《Monopoly GO!》荣耀再续!全球手游畅销榜冠军

易采游戏网5月22日消息&#xff0c;在刚刚过去的四月里&#xff0c;全球移动游戏市场的角逐愈发激烈。根据最新发布的数据&#xff0c;Scopely旗下的经典游戏《Monopoly GO!》再次蝉联全球手游畅销榜首冠军宝座&#xff0c;展现了无与伦比的市场魅力与玩家黏度。 4月Scopely《M…