675 lines
13 KiB
C++
675 lines
13 KiB
C++
#include "pch.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//获取EXE使用头 号位数据
|
|
int GetExeNutWrtNum(int Pos)
|
|
{
|
|
int num = *(int*)(0x40079F + (Pos * 4));
|
|
return num;
|
|
}
|
|
|
|
//写EXE使用头 号位数据
|
|
void SetExeNutWrtNum(int Pos, int num)
|
|
{
|
|
int* p = (int*)(0x40079F + (Pos * 4));
|
|
*p = num;
|
|
}
|
|
|
|
//获取Nut头 号位数据
|
|
int GetNutArrNum(int Nut头地址, int Pos )
|
|
{
|
|
int num = *(int*)(Nut头地址 + (Pos * 8));
|
|
return num;
|
|
}
|
|
|
|
//写Nut头 号位数据
|
|
void SetNutArrNum(int Nut头地址, int Pos, int num)
|
|
{
|
|
int* p = (int*)(Nut头地址 + (Pos * 8));
|
|
*p = num;
|
|
}
|
|
|
|
//读内存偏移地址
|
|
int GetHook(int Addr, std::string 地址)
|
|
{
|
|
size_t pos = 地址.find("+");
|
|
size_t size = 地址.size();
|
|
int GetHookArr[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
|
|
int i = 0;
|
|
|
|
while (pos != std::string::npos)
|
|
{
|
|
std::string x = 地址.substr(0, pos);
|
|
GetHookArr[i] = stoi(x, 0, 16);
|
|
i++;
|
|
地址 = 地址.substr(pos + 1, size);
|
|
pos = 地址.find("+");
|
|
}
|
|
|
|
int num;
|
|
num = *(int*)(Addr);
|
|
|
|
if (num != 0)
|
|
{
|
|
for (int z = 0; z < i; z++)
|
|
{
|
|
num = *(int*)(num + GetHookArr[z]);
|
|
}
|
|
}
|
|
return num;
|
|
}
|
|
|
|
|
|
|
|
//解密读取 句柄 地址
|
|
int DNFDeCode(int Address)
|
|
{
|
|
DWORD nEax, nEcx8, nEsi, nEdx, nTmp;
|
|
nEax = *(int*)(Address);
|
|
if (nEax == -1)
|
|
return nEax;
|
|
nEcx8 = *(int*)(Address + 8);
|
|
if (nEcx8 == -1)
|
|
return nEcx8;
|
|
nEsi = *(int*)(0x1AF8D78);
|
|
nEdx = nEax >> 16;
|
|
nTmp = (nEdx << 2) + nEsi + 36;
|
|
nEdx = *(int*)(nTmp);
|
|
if (nEdx == -1)
|
|
return nEdx;
|
|
nEax = nEax & 65535;
|
|
nTmp = (nEax << 2) + nEdx + 8468;
|
|
nEax = *(int*)(nTmp);
|
|
if (nEax == -1)
|
|
return nEax;
|
|
_asm
|
|
{
|
|
mov eax, nEax
|
|
movzx edx, ax
|
|
mov nEdx, edx
|
|
}
|
|
nEsi = nEdx << 16;
|
|
nEsi = nEsi | nEdx;
|
|
nEax = nEsi ^ nEcx8;
|
|
return nEax;
|
|
return 0;
|
|
}
|
|
//加密写入
|
|
void DNFEnCode(int AddreSs, int Data)
|
|
{
|
|
long JEdi, JEcx, JEax, JEsi, JEdx, JSs;
|
|
JEcx = AddreSs;
|
|
JEax = *(int*)(0x1AF8DB8);
|
|
JEax = JEax + 1;
|
|
*(int*)(0x1AF8DB8) = JEax;
|
|
JEdx = JEax;
|
|
JEdx = JEdx >> 8;
|
|
JEdx = JEdx << 24;
|
|
JEdx = JEdx >> 24;
|
|
JEdx = *(int*)(JEdx * 2 + 0x1843F58);
|
|
JEdx = JEdx & 0xFFFF;
|
|
JEax = JEax << 24;
|
|
JEax = JEax >> 24;
|
|
JSs = *(int*)(JEax * 2 + 0x1844158);
|
|
JSs = JSs & 0xFFFF;
|
|
JEdx = JEdx ^ JSs;
|
|
JEax = JEdx;
|
|
JEax = JEax & 0xFFFF;
|
|
JEsi = Data;
|
|
JEdx = JEsi >> 16;
|
|
Sleep(10);
|
|
JSs = JEsi & 0xFFFF;
|
|
JEdx = JEdx + JSs;
|
|
JEdx = JEdx ^ JEax;
|
|
JEdi = JEdx;
|
|
JEdx = JEax;
|
|
JEax = JEax << 16;
|
|
JEax = JEax + JEdx;
|
|
JEsi = Data;
|
|
JEax = JEax ^ JEsi;
|
|
JEsi = AddreSs + 8;
|
|
*(int*)(JEsi) = JEax;
|
|
JEax = *(int*)(AddreSs);
|
|
JEsi = *(int*)(0x1AF8D78);
|
|
|
|
JEcx = JEdi;
|
|
JEcx = JEcx << 16;
|
|
JEcx = JEcx + JEdx;
|
|
JEdx = JEax;
|
|
JEdx = JEdx >> 16;
|
|
JEdx = *(int*)(JEsi + JEdx * 4 + 36);
|
|
JEax = JEax & 0xFFFF;
|
|
*(int*)(JEdx + JEax * 4 + 8468) = JEcx;
|
|
}
|
|
|
|
|
|
int GetEquAddr(int addr)
|
|
{
|
|
switch (addr)
|
|
{
|
|
case 1:
|
|
return 0x3038;
|
|
break;
|
|
case 2:
|
|
return 0x304C;
|
|
break;
|
|
case 3:
|
|
return 0x3048;
|
|
break;
|
|
case 4:
|
|
return 0x3050;
|
|
break;
|
|
case 5:
|
|
return 0x3044;
|
|
break;
|
|
case 6:
|
|
return 0x3040;
|
|
break;
|
|
case 7:
|
|
return 0x3058;
|
|
break;
|
|
case 8:
|
|
return 0x305C;
|
|
break;
|
|
case 9:
|
|
return 0x3054;
|
|
break;
|
|
case 10:
|
|
return 0x3060;
|
|
break;
|
|
case 11:
|
|
return 0x3064;
|
|
break;
|
|
case 12:
|
|
return 0x3038;
|
|
break;
|
|
|
|
|
|
case 13:
|
|
return 0x3008;
|
|
break;
|
|
case 14:
|
|
return 0x300C;
|
|
break;
|
|
case 15:
|
|
return 0x3010;
|
|
break;
|
|
case 16:
|
|
return 0x3014;
|
|
break;
|
|
case 17:
|
|
return 0x3018;
|
|
break;
|
|
case 18:
|
|
return 0x301C;
|
|
break;
|
|
case 19:
|
|
return 0x3020;
|
|
break;
|
|
case 20:
|
|
return 0x3024;
|
|
break;
|
|
case 21:
|
|
return 0x3028;
|
|
break;
|
|
case 22:
|
|
return 0x302C;
|
|
break;
|
|
case 23:
|
|
return 0x3030;
|
|
break;
|
|
case 24:
|
|
return 0x3068;
|
|
break;
|
|
case 25:
|
|
return 0x306C;
|
|
break;
|
|
case 26:
|
|
return 0x3070;
|
|
break;
|
|
case 27:
|
|
return 0x3074;
|
|
break;
|
|
}
|
|
return -1;
|
|
}
|
|
//加载
|
|
static int SQloadfile(uint32_t v, const wchar_t* filename, bool printerror)
|
|
{
|
|
SQFILE* file = SQfopen(filename, L"rb+");
|
|
//FILE* file;
|
|
//file = fopen(filename, "rb");
|
|
int ret;
|
|
unsigned short us;
|
|
unsigned char uc;
|
|
LSQLEXREADFUNC func = SQ_io_file_lexfeed_ASCII;
|
|
if (file)
|
|
{
|
|
ret = SQfread(&us, 1, 2, file);
|
|
if (ret != 2)
|
|
{
|
|
us = 0;
|
|
}
|
|
if (us == 0xFAFA)
|
|
{
|
|
SQfseek(file, 0, 2);
|
|
if (SQ_Readclosure(v, SQ_File_read, file) > 0)
|
|
{
|
|
SQ__Fclose(file);
|
|
return SQ_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (us)
|
|
{
|
|
case 0xFFFE: func = SQ_io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;
|
|
case 0xFEFF: func = SQ_io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;
|
|
case 0xBBEF:
|
|
if (SQfread(&uc, 1, sizeof(uc), file) == 0)
|
|
{
|
|
SQ__Fclose(file);
|
|
return 1;
|
|
}
|
|
if (uc != 0xBF)
|
|
{
|
|
SQ__Fclose(file);
|
|
return 1;
|
|
}
|
|
func = SQ_io_file_lexfeed_UTF8;
|
|
break;//UTF-8 ;
|
|
default: SQfseek(file, 0, 2); break; // ascii
|
|
}
|
|
|
|
SQfseek(file, 0, 1);//定位到尾
|
|
int length = SQftell(file);//得到文件长度
|
|
SQfseek(file, 0, 2);//定位到头
|
|
|
|
|
|
char* temp = new char[length+4];//new一个新的字符串
|
|
|
|
SQfread(temp, sizeof(temp), length, file);//把文件读到字符串里
|
|
temp[length] = '\0';//给结尾添加结束符号
|
|
|
|
int key[] = { 5,2,3,5,0 };//定义解密数组
|
|
Cutecode(temp, key);//解密
|
|
|
|
SQFILE* newfile = SQfopen(L"ImagePacks2/sprite_interface_teart_zero.npk", L"wb+");//定义新的文件流
|
|
SQwrite(temp, sizeof(temp), strlen(temp), newfile);//写入
|
|
|
|
|
|
SQfseek(file, 0, 2);//定位到头
|
|
SQfseek(newfile, 0, 2);//定位到头
|
|
|
|
if (SQ_Compile(v, func, newfile, filename, printerror) >= 0)
|
|
{
|
|
SQ__Fclose(file);//关闭文件流
|
|
SQ__Fclose(newfile);//关闭文件流
|
|
remove("ImagePacks2/sprite_interface_teart_zero.npk");//删除文件
|
|
return SQ_OK;
|
|
}
|
|
}
|
|
SQ__Fclose(file);
|
|
return -1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int SQdofile(uint32_t v, const wchar_t* filename, bool retval, bool printerror)
|
|
{
|
|
if (SQloadfile(v, filename, printerror) >= 0)
|
|
{
|
|
SQPush(v, -2);
|
|
if ((int)SQ_Call(v, 1, retval, 1) >= 0)
|
|
{
|
|
SQ_Remove(v, -(retval != 0) - 1);
|
|
return 1;
|
|
}
|
|
SQPop(v, 1);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------Squirrel
|
|
//获取Squirrel v 基址
|
|
inline uint32_t GetSqVm()
|
|
{
|
|
return *(uint32_t*)0x1AF3544;
|
|
}
|
|
//新增nut接口funcName绑定C语言函数funcAddr
|
|
void RegisterNutApi(const wchar_t* funcName, void* funcAddr, uint32_t v)
|
|
{
|
|
if (!v)
|
|
v = GetSqVm();
|
|
SQPushRootTable(v);
|
|
SQPushString(v, funcName, -1);
|
|
RealSqNewClosure(v, funcAddr, 0);
|
|
SQNewSlot(v, -3, false);
|
|
SQPopTop(v);
|
|
}
|
|
//Test
|
|
static int sq_Test(uint32_t v)
|
|
{
|
|
//sq_pushinteger(v, n1);
|
|
return 0;
|
|
}
|
|
//读人物 或 装备属性
|
|
static int GetCharacterAttribute(uint32_t v)
|
|
{
|
|
int n1 ,n2 ;
|
|
int num = SQGetTop(v);
|
|
|
|
int CharAddr = *(int*)(0x1AB7CDC);
|
|
if (num == 3)
|
|
{
|
|
SQGetInt(v, 2, &n1);
|
|
SQGetInt(v, 3, &n2);
|
|
int TValue = *(int*)(CharAddr + GetEquAddr(n2));
|
|
int SValue = (TValue + n1);
|
|
if (n1 != 0x8 && n1 != 0x1C && n1 != 0xF4)
|
|
SQPushInt(v, (DNFDeCode(SValue)));
|
|
else
|
|
SQPushInt(v, (*(int*)(SValue)));
|
|
}
|
|
else if (num == 2)
|
|
{
|
|
SQGetInt(v, 2, &n1);
|
|
int Value = (CharAddr + n1);
|
|
|
|
SQPushInt(v, (DNFDeCode(Value)));
|
|
}
|
|
else
|
|
{
|
|
SQPushString(v, L"parameter error",-1);
|
|
}
|
|
return 1;
|
|
}
|
|
//写人物 或 装备属性
|
|
static int SetCharacterAttribute(uint32_t v)
|
|
{
|
|
int n1, n2, n3;
|
|
|
|
int num = SQGetTop(v);
|
|
|
|
int CharAddr = *(int*)(0x1AB7CDC);
|
|
if (num == 4)
|
|
{
|
|
SQGetInt(v, 2, &n1);
|
|
SQGetInt(v, 3, &n2);
|
|
SQGetInt(v, 4, &n3);
|
|
|
|
int TValue = *(int*)(CharAddr + GetEquAddr(n2));
|
|
int SValue = (TValue + n1);
|
|
if (n1 != 0x8 && n1 != 0x1C && n1 != 0xF4)
|
|
DNFEnCode(SValue, n3);
|
|
else
|
|
*(int*)SValue = n3;
|
|
SQPushBool(v, true);
|
|
}
|
|
else if (num == 3)
|
|
{
|
|
SQGetInt(v, 2, &n1);
|
|
SQGetInt(v, 3, &n2);
|
|
|
|
int Value = (CharAddr + n1);
|
|
DNFEnCode(Value, n2);
|
|
SQPushBool(v, true);
|
|
}
|
|
else
|
|
{
|
|
SQPushBool(v, false);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
//获取城镇编号
|
|
static int GetTownIndex(uint32_t v)
|
|
{
|
|
SQPushInt(v, GetHook(0x1A5E258, "0xAC+0xD4+"));
|
|
return 1;
|
|
}
|
|
//获取城镇区域编号
|
|
static int GetRegionIndex(uint32_t v)
|
|
{
|
|
SQPushInt(v, *(int*)(GetHook(0x1A5E258, "0xAC+0xD8+")));
|
|
return 1;
|
|
}
|
|
//获取城镇X坐标
|
|
static int GetTownXpos(uint32_t v)
|
|
{
|
|
SQPushInt(v, GetHook(0x1AB7CE0, "0x2BC+"));
|
|
return 1;
|
|
}
|
|
//获取城镇Y坐标
|
|
static int GetTownYpos(uint32_t v)
|
|
{
|
|
SQPushInt(v, GetHook(0x1AB7CE0, "0x2C0+"));
|
|
return 1;
|
|
}
|
|
|
|
//发包类型
|
|
static int SendPackType(uint32_t v)
|
|
{
|
|
int n1;
|
|
SQGetInt(v, 2, &n1);
|
|
_SendpacksType(*_SendClass, 0, n1);
|
|
|
|
SQPushInt(v, 1);
|
|
return 1;
|
|
}
|
|
|
|
//发包Byte
|
|
static int SendPackByte(uint32_t v)
|
|
{
|
|
int n1;
|
|
SQGetInt(v, 2, &n1);
|
|
_SendPacksByte(*_SendClass, 0, n1);
|
|
|
|
SQPushInt(v, 1);
|
|
return 1;
|
|
}
|
|
|
|
//发包Word
|
|
static int SendPackWord(uint32_t v)
|
|
{
|
|
int n1;
|
|
SQGetInt(v, 2, &n1);
|
|
_SendPacksWord(*_SendClass, 0, n1);
|
|
|
|
SQPushInt(v, 1);
|
|
return 1;
|
|
}
|
|
|
|
//发包DWord
|
|
static int SendPackDWord(uint32_t v)
|
|
{
|
|
int n1;
|
|
SQGetInt(v, 2, &n1);
|
|
_SendPacksDWord(*_SendClass, 0, n1);
|
|
|
|
SQPushInt(v, 1);
|
|
return 1;
|
|
}
|
|
|
|
//发包
|
|
static int SendPack(uint32_t v)
|
|
{
|
|
_SendPacks();
|
|
SQPushInt(v, 1);
|
|
return 1;
|
|
}
|
|
|
|
//发物品给玩家
|
|
static int GivePlayerItem(uint32_t v)
|
|
{
|
|
int n1,n2;
|
|
|
|
int num = SQGetTop(v);
|
|
|
|
if (num == 3)
|
|
{
|
|
SQGetInt(v, 2, &n1);
|
|
SQGetInt(v, 3, &n2);
|
|
|
|
_SendpacksType(*_SendClass, 0, 65);
|
|
_SendPacksDWord(*_SendClass, 0, 1);
|
|
_SendPacksDWord(*_SendClass, 0, n1);
|
|
_SendPacksDWord(*_SendClass, 0, n2);
|
|
_SendPacks();
|
|
|
|
SQPushBool(v, true);
|
|
}
|
|
else
|
|
{
|
|
SQPushBool(v, false);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//发装备给玩家
|
|
static int GivePlayerEqu(uint32_t v)
|
|
{
|
|
int n1, n2;
|
|
|
|
int num = SQGetTop(v);
|
|
|
|
if (num == 3)
|
|
{
|
|
SQGetInt(v, 2, &n1);
|
|
SQGetInt(v, 3, &n2);
|
|
|
|
_SendpacksType(*_SendClass, 0, 65);
|
|
_SendPacksDWord(*_SendClass, 0, 2);
|
|
_SendPacksDWord(*_SendClass, 0, n1);
|
|
_SendPacksDWord(*_SendClass, 0, n2);
|
|
_SendPacks();
|
|
|
|
SQPushBool(v, true);
|
|
}
|
|
else
|
|
{
|
|
SQPushBool(v, false);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//去副本
|
|
static int GoDungeon(uint32_t v)
|
|
{
|
|
int n1 = 0;
|
|
int n2 = 0;
|
|
int n3 = 0;
|
|
int n4 = 0;
|
|
|
|
int num = SQGetTop(v);
|
|
|
|
if (num == 2)
|
|
{
|
|
SQGetInt(v, 2, &n1);
|
|
}
|
|
else if (num == 5)
|
|
{
|
|
SQGetInt(v, 2, &n1);
|
|
SQGetInt(v, 3, &n2);
|
|
SQGetInt(v, 4, &n3);
|
|
SQGetInt(v, 5, &n4);
|
|
}
|
|
else
|
|
{
|
|
SQPushBool(v, false);
|
|
return 1;
|
|
}
|
|
|
|
_SendpacksType(*_SendClass, 0, 15);
|
|
_SendPacks();
|
|
|
|
_SendpacksType(*_SendClass, 0, 16);
|
|
_SendPacksWord(*_SendClass, 0, n1);
|
|
_SendPacksByte(*_SendClass, 0, n2);
|
|
_SendPacksByte(*_SendClass, 0, n3);
|
|
_SendPacksByte(*_SendClass, 0, n4);
|
|
_SendPacks();
|
|
|
|
SQPushBool(v, true);
|
|
return 1;
|
|
}
|
|
|
|
//Ldofile
|
|
static int LDofile(uint32_t v)
|
|
{
|
|
wchar_t* n1;
|
|
|
|
int num = SQGetTop(v);
|
|
|
|
if (num == 2)
|
|
{
|
|
SQGetString(v, 2, &n1);
|
|
SQPopTop(v);
|
|
/*
|
|
size_t len = wcslen(n1) + 1;
|
|
size_t converted = 0;
|
|
char* CStr;
|
|
CStr = (char*)malloc(len * sizeof(char));
|
|
wcstombs_s(&converted, CStr, len, n1, _TRUNCATE);
|
|
*/
|
|
|
|
SQdofile(v, n1, false, false);
|
|
SQPushBool(v, true);
|
|
}
|
|
else
|
|
{
|
|
SQPushBool(v, false);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void RegisterNut()
|
|
{
|
|
RegisterNutApi(L"L_sq_Test", sq_Test);
|
|
RegisterNutApi(L"L_sq_GetCharacterAttribute", GetCharacterAttribute);
|
|
RegisterNutApi(L"L_sq_SetCharacterAttribute", SetCharacterAttribute);
|
|
RegisterNutApi(L"L_sq_GetTownIndex", GetTownIndex);
|
|
RegisterNutApi(L"L_sq_GetRegionIndex", GetRegionIndex);
|
|
RegisterNutApi(L"L_sq_GetTownXpos", GetTownXpos);
|
|
RegisterNutApi(L"L_sq_GetTownYpos", GetTownYpos);
|
|
RegisterNutApi(L"L_sq_SendPackType", SendPackType);
|
|
RegisterNutApi(L"L_sq_SendPackByte", SendPackByte);
|
|
RegisterNutApi(L"L_sq_SendPackWord", SendPackWord);
|
|
RegisterNutApi(L"L_sq_SendPackDWord", SendPackDWord);
|
|
RegisterNutApi(L"L_sq_SendPack", SendPack);
|
|
RegisterNutApi(L"L_sq_GivePlayerItem", GivePlayerItem);
|
|
RegisterNutApi(L"L_sq_GivePlayerEqu", GivePlayerEqu);
|
|
RegisterNutApi(L"L_sq_GoDungeon", GoDungeon);
|
|
RegisterNutApi(L"L_sq_Dofile", LDofile);
|
|
}
|
|
|
|
|
|
|
|
|
|
|