51.x86游戏实战-XXX返回城镇的实现

news2024/11/25 2:35:51

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

本次游戏没法给

内容参考于:微尘网络安全

工具下载:

链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd=6tw3

提取码:6tw3

复制这段内容后打开百度网盘手机App,操作更方便哦

上一个内容:50.x86游戏实战-XXX副本内瞬图

上一个内容里找出了副本内切换地图的代码,接下把它封装到C++里,之后再找返回城镇的方式

新加副本内瞬移函数声明

代码

然后新加一个按钮

它的属性

双击按钮让它生成点击事件处理函数

副本内瞬移按钮的点击事件处理函数里的内容

然后副本内瞬移搞好了,接下来再搞返回城镇

打开游戏,然后打开OD附加到游戏,然后来到公共call

下图通过返回城镇

然后CTRL+F9,来到下图,可以看到下图位置它没有调用0x1127EC0,这为什么?

然后在下图位置打断点,看看它为什么没有0x1127EC0函数

断点住

然后按F7,看到它是通过jmp进入的0x1127EC0函数

然后接下来开始模拟这些代码,所以来到Dbgview.exe看这些发包函数的参数

然后发现模拟的代码调用完没有用,没法返回城镇,所以要找别的

pushad
push 0x7E
mov ecx, 0x1AEB6E4
mov ecx, [ecx]
mov eax, 0x1127D60
call eax

push 0x0
mov ecx, 0x1AEB6E4
mov ecx, [ecx]
mov eax, 0x11285B0
call eax


push 0x0
mov ecx, 0x1AEB6E4
mov ecx, [ecx]
mov eax, 0x11285B0
call eax

push 0x0
mov ecx, 0x1AEB6E4
mov ecx, [ecx]
mov eax, 0x11285B0
call eax

push 0x0
mov ecx, 0x1AEB6E4
mov ecx, [ecx]
mov eax, 0x11285B0
call eax

push 0x0
mov ecx, 0x1AEB6E4
mov ecx, [ecx]
mov eax, 0x11285B0
call eax

push 0x0
mov ecx, 0x1AEB6E4
mov ecx, [ecx]
mov eax, 0x11285B0
call eax

mov ecx, 0x1AEB6E4
mov ecx, [ecx]
mov eax, 0x1127EC0
call eax

popad

再次来到OD,来到公共call通过返回城镇触发断点,然后CTRL+F9

然后CTRL+F9

然后CTRL+F9

然后CTRL+F9

到了第五层,是call eax,不是call地址了,所以这里就可以停下CTRL+F9了,可以回头看了,找一个参数少好调用的函数

首先观察第4层

它有一个参数,然后它还有一个ecx,接下来找ecx

经过观察ecx的值应该来自于下图红框位置调用的函数

然后在下图红框位置打断点

然后返回城镇触发断点

然后取消断点

然后按F7

然后一路F8,主要观察eax的值在哪来的,然后看到eax的值来自于0x1A3CBF4

然后经过多次断点观察,它的入参一直是0x138D,所以可以模拟代码了

模拟的代码,它就可以正常返回城镇了

pushad
mov ecx,0x1A3CBF4
mov ecx,[ecx]
push 0x138D
mov eax,0x4E9740
call eax
popad

然后写到C++代码里

首先创建一个返回城镇的按钮

它的属性

双击下图红框生成点击事件处理函数

创建的函数

然后声明返回城镇的函数

然后右击函数名

然后选择下图红框

然后实现内容

然后点击事件处理函数

DXXDlg.cppw文件的内容:新加OnBnClickedButton10函数(副本内瞬移按钮点击事件处理函数)、OnBnClickedButton11函数(返回城镇按钮点击事件处理函数)

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

#include "pch.h"
#include "WCDXX.h"
#include "afxdialogex.h"
#include "DXXDlg.h"
#include "MyStrust.h"
#include "json.h"
#include "CLVEH.h"

// DXXDlg 对话框

IMPLEMENT_DYNAMIC(DXXDlg, CDialogEx)

DXXDlg::DXXDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG1, pParent)
{
	OutputDebugStringA("执行流程-执行DXXDlg构造函数流程1");
}

DXXDlg::~DXXDlg()
{
	OutputDebugStringA("执行流程-执行DXXDlg析构函数流程1");
}

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


BEGIN_MESSAGE_MAP(DXXDlg, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON1, &DXXDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &DXXDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &DXXDlg::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON4, &DXXDlg::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON5, &DXXDlg::OnBnClickedButton5)
	ON_BN_CLICKED(IDC_BUTTON6, &DXXDlg::OnBnClickedButton6)
	ON_BN_CLICKED(IDC_BUTTON7, &DXXDlg::OnBnClickedButton7)
	ON_BN_CLICKED(IDC_BUTTON8, &DXXDlg::OnBnClickedButton8)
	ON_BN_CLICKED(IDC_BUTTON9, &DXXDlg::OnBnClickedButton9)
	ON_BN_CLICKED(IDC_BUTTON10, &DXXDlg::OnBnClickedButton10)
	ON_BN_CLICKED(IDC_BUTTON11, &DXXDlg::OnBnClickedButton11)
END_MESSAGE_MAP()


// DXXDlg 消息处理程序


void DXXDlg::OnBnClickedButton1()
{
	MyStrust mystruct;
	mystruct.InitMy();
}


void DXXDlg::OnBnClickedButton2()
{

}


void DXXDlg::OnBnClickedButton3()
{
	
}


void DXXDlg::OnBnClickedButton4()
{
	MyStrust mystruct;
	mystruct.InitMy(); // 初始化玩家角色数据
	mystruct.ChangeBlooad(mystruct.My.Blood/2); // 修改血量
	
	// TODO: 在此添加控件通知处理程序代码
}


void DXXDlg::OnBnClickedButton5()
{
	MyStrust mystruct;
	mystruct.FindMaster();
}


void DXXDlg::OnBnClickedButton6()
{
	MyStrust mystruct;
	mystruct.AllKill();
}

// 断点的处理函数,ExceptionInfo里面有当前断点的寄存器的值
void fun(_EXCEPTION_POINTERS* ExceptionInfo) {
	call_loaA("wetool:EIP=%X,ECX=%X,参数=%X", ExceptionInfo->ContextRecord->Eip, ExceptionInfo->ContextRecord->Ecx, *(DWORD*)(ExceptionInfo->ContextRecord->Esp + 4));
}

// HOOK按钮的点击事件处理函数
void DXXDlg::OnBnClickedButton7()
{
	// 调用AddVeh添加要下断点的地址,地址不要写重了,写重了关闭断点的时候游戏会闪退
	CCLVEH::Instance()->AddVeh("n1", 0, 0, 0x01127D60, 1, 0, fun);
	CCLVEH::Instance()->AddVeh("n2", 0, 0, 0x01128550, 1, 0, fun);
	CCLVEH::Instance()->AddVeh("n3", 0, 0, 0x01128580, 1, 0, fun);
	CCLVEH::Instance()->AddVeh("n4", 0, 0, 0x011285B0, 1, 0, fun);
	// 下断点
	CCLVEH::Instance()->InitVeh();
}

// 卸载HOOK按钮的点击事件处理函数
void DXXDlg::OnBnClickedButton8()
{
	// 关闭断点
	CCLVEH::Instance()->ExitVeh();
}

// 秒进地图按钮点击事件处理函数
void DXXDlg::OnBnClickedButton9()
{
	MyStrust mystruct;
	mystruct.StartIn();

}


// 副本内瞬移按钮点击事件处理函数
void DXXDlg::OnBnClickedButton10()
{
	MyStrust mystruct;
	mystruct.MoveInMap(1, 1);
}

// 返回城镇按钮点击事件处理函数
void DXXDlg::OnBnClickedButton11()
{
	MyStrust mystruct;
	mystruct.ComeBackTwon();
}

MyStrust.cpp文件的内容:新加 MoveInMap函数、ComeBackTwon函数

#include "pch.h"
#include "MyStrust.h"

void MyStrust::InitMy()
{
	//  [[0x1AB7CDC]+0x258] 名字
	/*
		*这个符号表示地址,在c++中被称为指针或指针类型
		int表示4字节数字
		int*就表示指针类型的int
		(int*)0x1AB7CDC;这样表示0x1AB7CDC地址里的内容是4字节的数字
	*/
	int* address = (int*)0x1AB7CDC;
	/*
		取出地址中的值,也就是取出0x1AB7CDC里的内容
		*address这样在左边只写一个*表示取内存地址里的值
		也就是取address它的值,address是0x1AB7CDC,也就是取0x1AB7CDC它的值

	*/
	int addressValue = *address;
	/*
		(*(int*)addressValue)意思是
		把addressValue转成int*,也就是把
		addressValue的值当成内存地址,addressValue的值现在是[0x1AB7CDC]+0x258这个
		现在这个地址里面的值是名字的地址,所以在左边加了一个*让把名字的地址去除了出来
		取出来之后就得到了名字,名字是UNICODE类型,UNICODE又被称为宽字节,宽字节的数据是用两个字节描述一个文字或字母
		在c++里wchar_t类型就是UNICODE
		然后在c++中名字这种数据被称为字符串,如果要用字符串必须用指针类型也就是wchar_t*
		右边加上*让wchar_t变成指针类型的wchar_t,才能在c++中使用字符串

	*/
	this->My.Name = (wchar_t*)(*(int*)(addressValue+0x258));
	// 一般函数名后面是W就表示有UNICODE,也就是要用宽字节
	// OutputDebugStringW(this->My.Name);
	// L""这两个"之间表示字符串,L""表示这个字符串是宽字节(使用Unicode编码)
	call_logW(L"wetool:人物姓名=%ws,测试=%ws", this->My.Name,L" 52am");
	//  [[0x1AB7CDC]+0x18C]x坐标
	//  [[0x1AB7CDC]+0x190]y坐标
	/*
		取出地址中的值,也就是取出0x1AB7CDC里的内容
		*address这样在左边只写一个*表示取内存地址里的值
		也就是取address它的值,address是0x1AB7CDC,也就是取0x1AB7CDC它的值

	*/
 
	this->My.X= *(float*)(addressValue + 0x18C);
	this->My.Y = *(float*)(addressValue + 0x190);
	char buf[256] = { 0 };
	// 拼接文字,%f表示拼接一个小数(单浮点数)
	sprintf(buf, "wetool:x=%f;y=%f", this->My.X, this->My.Y);
	OutputDebugStringA(buf);

	// [[0x1AB7CDC]+0x36A0]血量
	this->My.Blood = *(int*)(addressValue + 0x36A0);
	// 拼接文字,%d表示拼接一个整数(32位的整数)
	sprintf(buf, "wetool:血量 = %d", this->My.Blood);
	OutputDebugStringA(buf);
}

void MyStrust::UseObject(DWORD object)
{
	object += 3; // 背包物品序号
	/*
	  try的作用
		如果
		__asm {
			pushad
			push object
			mov ecx, 0x1A5FB24 // 背包基址
			mov ecx, [ecx]
			mov eax, 0x7B9130 // 使用物品的函数地址
			call eax
			popad
		}
		这个代码运行过程中出现错误了,我不会让游戏崩溃,出现错误之后会执行
		catch (...) {
			OutputDebugStringA("MyStrust::UseObject error");
		}
		这个catch里面的代码,现在也就是执行OutputDebugStringA("MyStrust::UseObject error");这一行
	*/
	try { 
		__asm {
			pushad
			push object
			mov ecx, 0x1A5FB24 // 背包基址
			mov ecx, [ecx]
			mov eax, 0x7B9130 // 使用物品的函数地址
			call eax 
			popad
		}
	}
	catch (...) {
		OutputDebugStringA("MyStrust::UseObject error");
	}
}

void MyStrust::ChangeBlooad(int v)
{
	try {
		__asm {
			pushad
			push 0
			push 0
			push 0
			push v
			mov ecx, 0x1AB7CDC // 里面有我们玩家角色数据的基址
			mov ecx, [ecx]
			mov eax, 0x8174E0 // 修改血量的函数地址
			call eax
			popad
		}
	}
	catch (...) {
		OutputDebugStringA("MyStrust::ChangeBlooad error");
	}
}

void MyStrust::NewChangeBlooad(DWORD nEcx)
{
	try {
		__asm {
			pushad
			push 0
			push 0
			push 0
			push 0
			mov ecx, nEcx
			mov eax, 0x8174E0 // 修改血量的函数地址
			call eax
			popad
		}
	}
	catch (...) {
		OutputDebugStringA("MyStrust::NewChangeBlooad error");
	}
}

// 遍历怪物列表函数,加吸怪
void MyStrust::FindMaster()
{
	wchar_t* Tmp1;
	/* 
		[[[[[0x1A5E258]+3*4+0xA8]+0x14]+0x88]+0x10]
		下方 ReadDword 函数通过 [[[[[0x1A5E258]+3*4+0xA8]+0x14]+0x88]+0x10] 这个取值算法得到附近列表(怪物列表)
	*/
	DWORD Tmp = ReadDword(ReadDword(ReadDword(ReadDword(ReadDword(0x1A5E258) + 0x3 * 4 + 0xA8) + 0x14) + 0x88) + 0x10);
	if (Tmp != 0) {// 如果是0说明没有找到怪物列表
		for (size_t i = 0; i < 100; i++)// 这里的100是随便写的
		{
			if (ReadDword(Tmp + i * 4)>0 && (ReadDword(ReadDword(Tmp + i * 4) + 0x90) == 0x211)) {
			//if (ReadDword(Tmp + i * 4)>0) {
				Tmp1 = (wchar_t*)ReadDword(ReadDword(Tmp + i * 4) + 0x258); // 0x258位置是名字
				if (Tmp1 == 0) {// 如果是0说明没有名字
					 //call_logW(L"wetool:NULL\n");
					 this->masterNum.Name[i] = L"";
				}
				else {
					/*
						打印名字到 Dbgview.exe,其中 wetool这个是为了过滤 Dbgview.exe打印的一些跟我们不相关的日志

					*/
					//call_logW(L"wetool:%ws\n", Tmp1);
					this->masterNum.Name[i] = Tmp1;
				}
				// 血量与玩家角色不是一个位置,可以在修改血量的位置追,这个不重要,后面有机会再找
				//masterNum.Blood[i] = ReadDword(ReadDword(Tmp + i * 4) + 0x90); 
				this->masterNum.type[i] = ReadDword(ReadDword(Tmp + i * 4) + 0x90);
				this->masterNum.x[i] = ReadFloat(ReadDword(Tmp + i * 4) + 0x18C);
				this->masterNum.y[i] = ReadFloat(ReadDword(Tmp + i * 4) + 0x190);
				
				this->masterNum.x[i] = this->My.X;
				this->masterNum.y[i] = this->My.Y;
				this->masterNum.Object[i] = ReadDword(Tmp + i * 4);
				
				*(FLOAT*)(ReadDword(ReadDword(Tmp + i * 4) + 0xA8) + 0xC) = this->My.X; // 修改之后会瞬移的坐标,把它的值赋值成我们玩家的坐标
				*(FLOAT*)(ReadDword(ReadDword(Tmp + i * 4) + 0xA8) + 0x10) = this->My.Y; // 修改之后会瞬移的坐标,把它的值赋值成我们玩家的坐标
				call_logW(L"wetool:第%d个对象:%x 怪物名字:%ls type:0x%x x:%f y:%f", i, this->masterNum.Object[i], this->masterNum.Name[i], this->masterNum.type[i], this->masterNum.x[i], this->masterNum.y[i]);
			}
		}
	}
	else {
		call_loaA("wetool:Tmp error");
	}
}

// 吸怪加秒杀
void MyStrust::AllKill()
{
	try {
	this->InitMy();
	this->FindMaster();
	for (size_t i = 0; i < 100; i++)
	{
		if (this->masterNum.Object[i] > 0 && (this->masterNum.type[i] == 0x211)) {
		
				call_logW(L"wetool:AllKill-第%d个对象:%x 怪物名字:%ls type:0x%x x:%f y:%f", i, this->masterNum.Object[i], this->masterNum.Name[i], this->masterNum.type[i], this->masterNum.x[i], this->masterNum.y[i]);
				this->NewChangeBlooad(this->masterNum.Object[i]);// 调用修改血量的函数
		}
	}
	}
	catch (...) {
		OutputDebugStringA("MyStrust::AllKill error");
	}
}

void MyStrust::StartIn()
{
	try {
		__asm
		{
			pushad
			// 切换地图
			push 0x26
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1127D60
			call eax

			push 0xE
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128550
			call eax

			push 0x2
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128550
			call eax

			push 0x1E
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128580
			call eax

			push 0x10F
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128580
			call eax

			push 0x5
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128550
			call eax

			push 0xE
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128580
			call eax

			push 0x1
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128580
			call eax

			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1127EC0
			call eax
			// 进入副本选择界面
			push 0xF
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1127D60
			call eax

			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1127EC0
			call eax
			// 进入副本
			push 0x10
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1127D60
			call eax

			push 0x68
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128580
			call eax

			push 0
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128550
			call eax

			push 0
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128550
			call eax

			push 0
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1128550
			call eax

			mov eax, 0x1127EC0
			call eax

			popad

			// 进入副本选择界面
			pushad

			push 0xF
			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1127D60
			call eax

			mov ecx, 0x1AEB6E4
			mov ecx, [ecx]
			mov eax, 0x1127EC0
			call eax
			popad

		}
	}
	catch (...)
	{
		OutputDebugStringA(" MyStrust::StartIn error");
	}

}

void MyStrust::MoveInMap(DWORD x, DWORD y)
{
	try {
		DWORD nEcx = *(DWORD*)0x1AEB6E4;
		__asm {
			pushad

			push 0x30
			mov ecx, nEcx
			mov eax, 0x1127D60
			call eax

			// 这里的0x2它是地图x的数据
			push x
			mov ecx, nEcx
			mov eax, 0x1128550
			call eax
			// 这里的0x1它是地图y的数据
			push y
			mov ecx, nEcx
			mov eax, 0x1128550
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x11285B0
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x11285B0
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x1128550
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x1128580
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x1128580
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x1128580
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x1128580
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x1128580
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x11285B0
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x11285B0
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x11285B0
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x11285B0
			call eax

			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x1128580
			call eax
			// 入参没用
			push 0x0
			mov ecx, nEcx
			mov eax, 0x11285B0
			call eax

			mov ecx, nEcx
			mov eax, 0x1127EC0
			call eax

			popad
		}
	}catch (...) {
		OutputDebugStringA(" MyStrust::StartIn error");
	}

}

void MyStrust::ComeBackTwon()
{
	try {
		DWORD nEcx = *(DWORD*)0x1AEB6E4;
		__asm {
			pushad
			mov ecx, 0x1A3CBF4
			mov ecx, [ecx]
			push 0x138D
			mov eax, 0x4E9740
			call eax
			popad
		}
	}
	catch (...) {
		OutputDebugStringA(" MyStrust::ComeBackTwon error");
	}
}

MyStrust.h文件的内容:新加 MoveInMap函数声明、ComeBackTwon函数声明

#pragma once
struct Myself {
	DWORD Blood;// 血量
	FLOAT X; // x坐标
	FLOAT Y; // y坐标
	wchar_t* Name; // 名字
};

struct Master {
	DWORD Object[100];
	DWORD Blood[100];
	FLOAT x[100];
	FLOAT y[100];
	wchar_t* Name[100];
	DWORD type[100];
};

class MyStrust
{
public:
	Myself My;
	Master masterNum;
	void InitMy();// 玩家角色基本信息(血量、名字、坐标)
	void UseObject(DWORD object); // 修改血量
	void ChangeBlooad(int v); // 使用物品
	void NewChangeBlooad(DWORD nEcx);
	void FindMaster();// 遍历怪物
	void AllKill(); // 吸怪加秒杀
	void StartIn();// 秒进副本
	void MoveInMap(DWORD x, DWORD y); // 副本内瞬移
	void ComeBackTwon(); // 返回城镇
};

上方的代码不全,只有手写的代码

完整代码:以 49.x86游戏实战-C++实现秒进图 它的代码为基础进行修改

链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg?pwd=q9n5

提取码:q9n5

复制这段内容后打开百度网盘手机App,操作更方便哦


img

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用智谱AI大模型翻译视频字幕

不久前&#xff0c;国内的头部大模型厂商智谱 AI &#xff0c;刚刚推出了 glm-4-0520 模型&#xff0c;该模型被认为是当前平台最先进的模型&#xff0c;具备 128k 的上下文长度&#xff0c;并且相较于前一代模型&#xff0c;指令遵从能力大幅提升 18.6%。可以看出&#xff0c;…

一键开启,精彩即现!极简设计录屏软件大盘点

如果你想要用一款小巧的录屏工具&#xff0c;第一时间是不是就想到了ocam录屏&#xff0c;现在这类的简便录屏工具越来越多了&#xff0c;如果你想要换一个不妨接着往下看吧。 1.福昕录屏大师 链接&#xff1a;www.foxitsoftware.cn/REC/ 这个软件的界面看起来就很好操作&am…

《HelloGitHub》第 101 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

测试 UDP 端口可达性的方法

前言&#xff1a; UDP (User Datagram Protocol) 是一种无连接的传输层协议&#xff0c;它不像 TCP 那样提供确认机制来保证数据包的可靠传输。因此&#xff0c;测试 UDP 端口的可达性通常需要一些特殊的方法&#xff0c;因为传统的端口扫描工具&#xff08;如 nmap&#xff0…

【开源 Mac 工具推荐之 5】tldr:简洁明了的命令行手册显示工具

简介 在大家日常在 macOS/Linux 上使用 Shell 的时候&#xff0c;常常会遇到一些不太熟悉的命令行指令&#xff0c;为此我们一般会查看一下该命令的使用手册&#xff08;指南&#xff09;。往往&#xff0c;大家都会使用 man <command> 这样一个非常传统的指令。但 man …

YOLOv8改进 | 融合改进 | C2f融合Faster-GELU模块提升检测速度【完整代码 + 主要代码解析】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效…

Unity URPShader支持多光源处理

//声明变体并且引用文件 #pragma shader_feature _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" //在数据结构体中声明需要使用的数据 struct Attributes {float4 posit…

如何写一份简单的3C产品说明书?五步让你留住客源

在撰写3C&#xff08;计算机、通信、消费电子&#xff09;产品说明书时&#xff0c;清晰、简洁且全面的信息传递至关重要。本文将首先介绍产品说明书的基本结构&#xff0c;随后探讨视觉阅读的重要性&#xff0c;并通过实例展示如何撰写一份优秀的产品说明书。最后&#xff0c;…

SpringBoot2:学SpringBoot前的知识准备-用IDEA创建传统的webapp工程,并整合SpringMVC

1、IDEA创建工程 基于Maven模板创建的SpringMVC工程 工程创建好后&#xff0c;只有webapp目录 这里&#xff0c;我们需要手动创建java目录和resources配置文件目录 创建好后&#xff0c;配置下目录属性 最终结构 至此&#xff0c;工程就创建好了 2、配置Tomcat 参考&am…

LabVIEW中10μs方波生成问题

在LabVIEW中使用NI PCIe-6353卡生成并控制10μs级别的方波输出可能遇到频率调整的问题。下面将详细分析常见问题的原因&#xff0c;如采样率设置、时钟源配置、波形生成方式等&#xff0c;并提供具体的解决方案&#xff0c;帮助用户成功生成并调整高精度方波信号。 为了在LabVI…

孙悟空求药的深刻反思

孙悟空求药的深刻反思 - 孔乙己大叔引言&#xff1a;孙悟空的求药之旅 在古老的神话故事中&#xff0c;孙悟空为了拯救乌鸡国国王的生命&#xff0c;不惜跨越千山万水&#xff0c;前往太上老君的仙宫&#xff0c;祈求那传说中的九转还魂丹。面对孙悟空那看似贪婪的一千…

【案例65】WebSphere启动比tomcat启动慢的测试

以下为多次测试的一些结论&#xff0c;谨慎使用&#xff0c;请一定做好测试后在使用。 1.在原先慢的WAS环境下&#xff0c;添加-Dsun.reflect.inflationThreshold15,可以有效提升was下的响应速度&#xff0c;和Tomcat下速度相当&#xff0c;但该参数15的情况我们Tomcat以前还没…

FastGPT:利用大模型重新定义传统知识库

引言 传统知识库的痛点 传统知识库广泛应用于企业文档管理、客户支持等场景&#xff0c;但随着信息量和复杂度的增加&#xff0c;存在以下显著问题&#xff1a; 数据难整合&#xff1a; 结构化与非结构化数据分散&#xff0c;更新维护成本高。检索不精准&#xff1a; 依赖关…

day03-面向对象-内部类泛型常用API

一、内部类 内部类是类中的五大成分之一&#xff08;成员变量、方法、构造器、代码块、内部类&#xff09; 如果一个类定义在另一个类的内部&#xff0c;这个类就是内部类。 场景&#xff1a;当一个类的内部&#xff0c;包含了一个完整的事物&#xff0c;且这个事物没有必要单…

Go发布自定义包

1、初始化go.mod go mod init github.com/xumeng03/images2、编写包内容 这里只是一个简单的压缩jpg/jpeg图片例子&#xff0c;代码参考 https://github.com/disintegration/imaging 2.1、fs.go package imagesimport ("image""io""os""p…

利用通义灵码实现我的第一次开源贡献

作者&#xff1a;重庆邮电大学计算机学院李逸雄 结缘开源 最早了解开源是从学校的兴趣组织开始的。2023 年 10 月 21 日&#xff0c;openSUSE 亚洲峰会在我们学校召开&#xff0c;这次会议汇聚了许多来自 openSUSE 社区贡献者以及对开源感兴趣的爱好者们。我第一次知道有这么…

postman使用记录

输入密码&#xff0c;地址 然后输入格式为json 在 body里写入传参 然后点击发送即可

裸机:SD卡启动详解

内存和外存的区别 内存和外存在计算机系统中扮演着不同的角色&#xff0c;它们之间存在显著的差异。以下是内存和外存之间几个主要方面的区别&#xff1a; 存储特性与易失性 内存&#xff08;Memory&#xff09;&#xff1a;通常指的是随机存取存储器&#xff08;RAM&#x…

Java面试题·区别题·JavaSE部分

系列文章目录 总章 Java区别题 文章目录 系列文章目录前言private/默认/protected/public权限修饰符的区别&和&&区别和联系&#xff0c;I和II区别和联系if和switch的不同之处和equals的区别和联系数组做形参和可变参数做形参联系和区别接口和抽象类的异同之处面向…