Jump to content
  • 0

Automatic verify and ban unauthorized skills - L2JFrozen


Question

Posted

Hello, i need some help if anyone know:

 

I have a multiskill server (L2JFrozen rev) and I've recently had some hacker enter my server and he was able to learn monster passive skills/active skills and some skills that aren't in any character skill tree, like valakas buff, super haste, etc.

 

Since it happened i activated the AllowedSkills function (plus also activating it on the Protected folder CheckSkillsOnEnter), and added on the list only the character skills on the list (1-500 and 1000-1500), however, the function doesn't seem to be working.

 

Is there a way a can put a verification on L2PcInstance or some other java instance to automatically ban player/delete skills between 3000-7000 or something like that? My source code already has something like this (i'll be posting below), but it doesn't seem to be working (i tested with another character and nothing happened to it).

 

	/**
	 * check player skills and remove unlegit ones (excludes hero, noblesse and cursed weapon skills).
	 */
	public void checkAllowedSkills()
	{
		boolean foundskill = false;
		if (!isGM())
		{
			Collection<L2SkillLearn> skillTree = SkillTreeTable.getInstance().getAllowedSkills(getClassId());
			// loop through all skills of player
			for (final L2Skill skill : getAllSkills())
			{
				final int skillid = skill.getId();
				// int skilllevel = skill.getLevel();
				
				foundskill = false;
				// loop through all skills in players skilltree
				for (final L2SkillLearn temp : skillTree)
				{
					// if the skill was found and the level is possible to obtain for his class everything is ok
					if (temp.getId() == skillid)
					{
						foundskill = true;
					}
				}
				
				// exclude noble skills
				if (isNoble() && skillid >= 325 && skillid <= 397)
				{
					foundskill = true;
				}
				
				if (isNoble() && skillid >= 1323 && skillid <= 1327)
				{
					foundskill = true;
				}
				
				// exclude hero skills
				if (isHero() && skillid >= 395 && skillid <= 396)
				{
					foundskill = true;
				}
				
				if (isHero() && skillid >= 1374 && skillid <= 1376)
				{
					foundskill = true;
				}
				
				// exclude cursed weapon skills
				if (isCursedWeaponEquiped() && skillid == CursedWeaponsManager.getInstance().getCursedWeapon(_cursedWeaponEquipedId).getSkillId())
				{
					foundskill = true;
				}
				
				// exclude clan skills
				if (getClan() != null && skillid >= 370 && skillid <= 391)
				{
					foundskill = true;
				}
				
				// exclude seal of ruler / build siege hq
				if (getClan() != null && (skillid == 246 || skillid == 247))
					if (getClan().getLeaderId() == getObjectId())
					{
						foundskill = true;
					}
				
				// exclude fishing skills and common skills + dwarfen craft
				if (skillid >= 1312 && skillid <= 1322)
				{
					foundskill = true;
				}
				
				if (skillid >= 1368 && skillid <= 1373)
				{
					foundskill = true;
				}
				
				// exclude sa / enchant bonus / penality etc. skills
				if (skillid >= 3000 && skillid < 7000)
				{
					foundskill = true;
				}
				
				// exclude Skills from AllowedSkills in options.properties
				if (Config.ALLOWED_SKILLS_LIST.contains(skillid))
				{
					foundskill = true;
				}
				
				// exclude Donator character
				if (isDonator())
				{
					foundskill = true;
				}
				
				// exclude Aio character
				if (isAio())
				{
					foundskill = true;
				}
				
				// remove skill and do a lil LOGGER message
				if (!foundskill)
				{
					removeSkill(skill);
					
					if (Config.DEBUG)
					{
						// sendMessage("Skill " + skill.getName() + " removed and gm informed!");
						LOGGER.warn("Character " + getName() + " of Account " + getAccountName() + " got skill " + skill.getName() + ".. Removed!"/* + IllegalPlayerAction.PUNISH_KICK */);
						
					}
				}
			}
			
			// Update skill list
			sendSkillList();
			
			skillTree = null;
		}
	}
	

 

 

Recommended Posts

  • 0
Posted
6 minutes ago, dextroy said:

I understand, but i'm not sure if i can cover every single possibility of "how he did it" as there were no specific logs generated. 

 

The normal learn skill process on my server calls for the database skill tree on class masters, and the db skill tree only displays skills under 1500, which are the regular skill classes.

 

image.png.883504599d4d172595c9508cc89d5a85.png

 

If he used a class master to learn the skill, the new line i added on my previous post should already block them from learning. But if he did some other way, i can't figure out 'cause there were no logs.

 

And i think i can assume it's not addSkill command 'cause only GM/ADM access level can call for those. And i'm assuming it's nothing of the sort, because if it was, he could've cause more damage than simply learning monster/items skills.

Did you carefully read what I wrote?
ADM / GM has nothing to do with it, I make it clear that you think narrowly.

You are trying to guess how he does it, although you have an understanding of what he does.

 

Any skill that a character gains goes through the skill addition method. You can also track the hacker through it.   

  • 0
Posted
16 hours ago, dextroy said:

Hello, i need some help if anyone know:

 

I have a multiskill server (L2JFrozen rev) and I've recently had some hacker enter my server and he was able to learn monster passive skills/active skills and some skills that aren't in any character skill tree, like valakas buff, super haste, etc.

 

Since it happened i activated the AllowedSkills function (plus also activating it on the Protected folder CheckSkillsOnEnter), and added on the list only the character skills on the list (1-500 and 1000-1500), however, the function doesn't seem to be working.

 

Is there a way a can put a verification on L2PcInstance or some other java instance to automatically ban player/delete skills between 3000-7000 or something like that? My source code already has something like this (i'll be posting below), but it doesn't seem to be working (i tested with another character and nothing happened to it).

 

	/**
	 * check player skills and remove unlegit ones (excludes hero, noblesse and cursed weapon skills).
	 */
	public void checkAllowedSkills()
	{
		boolean foundskill = false;
		if (!isGM())
		{
			Collection<L2SkillLearn> skillTree = SkillTreeTable.getInstance().getAllowedSkills(getClassId());
			// loop through all skills of player
			for (final L2Skill skill : getAllSkills())
			{
				final int skillid = skill.getId();
				// int skilllevel = skill.getLevel();
				
				foundskill = false;
				// loop through all skills in players skilltree
				for (final L2SkillLearn temp : skillTree)
				{
					// if the skill was found and the level is possible to obtain for his class everything is ok
					if (temp.getId() == skillid)
					{
						foundskill = true;
					}
				}
				
				// exclude noble skills
				if (isNoble() && skillid >= 325 && skillid <= 397)
				{
					foundskill = true;
				}
				
				if (isNoble() && skillid >= 1323 && skillid <= 1327)
				{
					foundskill = true;
				}
				
				// exclude hero skills
				if (isHero() && skillid >= 395 && skillid <= 396)
				{
					foundskill = true;
				}
				
				if (isHero() && skillid >= 1374 && skillid <= 1376)
				{
					foundskill = true;
				}
				
				// exclude cursed weapon skills
				if (isCursedWeaponEquiped() && skillid == CursedWeaponsManager.getInstance().getCursedWeapon(_cursedWeaponEquipedId).getSkillId())
				{
					foundskill = true;
				}
				
				// exclude clan skills
				if (getClan() != null && skillid >= 370 && skillid <= 391)
				{
					foundskill = true;
				}
				
				// exclude seal of ruler / build siege hq
				if (getClan() != null && (skillid == 246 || skillid == 247))
					if (getClan().getLeaderId() == getObjectId())
					{
						foundskill = true;
					}
				
				// exclude fishing skills and common skills + dwarfen craft
				if (skillid >= 1312 && skillid <= 1322)
				{
					foundskill = true;
				}
				
				if (skillid >= 1368 && skillid <= 1373)
				{
					foundskill = true;
				}
				
				// exclude sa / enchant bonus / penality etc. skills
				if (skillid >= 3000 && skillid < 7000)
				{
					foundskill = true;
				}
				
				// exclude Skills from AllowedSkills in options.properties
				if (Config.ALLOWED_SKILLS_LIST.contains(skillid))
				{
					foundskill = true;
				}
				
				// exclude Donator character
				if (isDonator())
				{
					foundskill = true;
				}
				
				// exclude Aio character
				if (isAio())
				{
					foundskill = true;
				}
				
				// remove skill and do a lil LOGGER message
				if (!foundskill)
				{
					removeSkill(skill);
					
					if (Config.DEBUG)
					{
						// sendMessage("Skill " + skill.getName() + " removed and gm informed!");
						LOGGER.warn("Character " + getName() + " of Account " + getAccountName() + " got skill " + skill.getName() + ".. Removed!"/* + IllegalPlayerAction.PUNISH_KICK */);
						
					}
				}
			}
			
			// Update skill list
			sendSkillList();
			
			skillTree = null;
		}
	}
	

 

 

If I remember correctly, this bug used to work on old Interlude versions using PHX. Where you request to learn an skill, but in reality you send other skill through phx. Put there a check to verify if that skill that is beeing added belongs to that class. If not, simply ignore. If you want to use that method you specified, use it more times on teleport, certain actions, enter/leave zone... Although its not an fix but rather an shortcut to dealing with your problem.

  • 0
Posted
16 minutes ago, Psygrammator said:

Did you carefully read what I wrote?
ADM / GM has nothing to do with it, I make it clear that you think narrowly.

You are trying to guess how he does it, although you have an understanding of what he does.

 

Any skill that a character gains goes through the skill addition method. You can also track the hacker through it.   

Ok, but what should i be looking into then? What java file? I'm trying to understand within my knowledge, which is not that advanced, so i ask for some patience. I did what i said about skills > 1500 on RequestAquireSkill.java. Is that enough?

 

7 minutes ago, HyperBlown said:

If I remember correctly, this bug used to work on old Interlude versions using PHX. Where you request to learn an skill, but in reality you send other skill through phx. Put there a check to verify if that skill that is beeing added belongs to that class. If not, simply ignore. If you want to use that method you specified, use it more times on teleport, certain actions, enter/leave zone... Although its not an fix but rather an shortcut to dealing with your problem.

And is there a way i can verify/block what that phx sends? I'm not experienced with hack systems, so i don't know exactly how it's done. Where would i put that verification, considering the server is multiskill and it should allow all classes skills (skills under 1500)? And i don't know exactly where to put the method i asked for, that's why i'm here, i don't know which java file or how to code as i'm not an experienced developer/programmer.

  • 0
Posted (edited)
9 minutes ago, dextroy said:

Ok, but what should i be looking into then? What java file? I'm trying to understand within my knowledge, which is not that advanced, so i ask for some patience. I did what i said about skills > 1500 on RequestAquireSkill.java. Is that enough?

 

And is there a way i can verify/block what that phx sends? I'm not experienced with hack systems, so i don't know exactly how it's done. Where would i put that verification, considering the server is multiskill and it should allow all classes skills (skills under 1500)? And i don't know exactly where to put the method i asked for, that's why i'm here, i don't know which java file or how to code as i'm not an experienced developer/programmer.

There can be many reasons for how he does this, if l2phx, then protection is needed that will encrypt the packets so that the hacker cannot send them modified. (What l2phx is using is guesswork from the user above)
 

If this is a bug in the emulator, no amount of protection will help you until you find the cause. To find the reason, I gave you a detailed answer above how to track the process, how a hacker does it, and through which class.

Edited by Psygrammator
  • 0
Posted
6 minutes ago, Psygrammator said:

There can be many reasons for how he does this, if l2phx, then protection is needed that will encrypt the packets so that the hacker cannot send them modified. (What l2phx is using is guesswork from the user above)
 

If this is a bug in the emulator, no amount of protection will help you until you find the cause. To find the reason, I gave you a detailed answer above how to track the process, how a hacker does it, and through which class.

 

I appreciate that, but being honest i still couldn't understand what my next steps should be. Tracing the code could literally be looking into every single .java file, and as i said, i'm not a programmer/developer.

 

That's why i've been asking as least for a countermeasure, if someone is sending illegal packets that i can't track (i don't know how or it'd require too much programming knowlege), wouldn't a block on it's effects at least partially solve the issue?

 

I still don't know where to look at. If you could pinpoint something like: "You can add some code lines on WhateverFile.java and it will verify the skills" and somewhat of what the code would look like, then i can attempt a solution here.

 

But i'm not at advanced knowledge with java. Tracing everything, check packets, hacking, those are not things i'm experenced at, so i just honestly don't know where to start looking. With the information i'm receiving.

 

Zake told me to look on RequestAquireSkill.java and i was able to put an extra code line there. But i don't know if that's enough or where else i could put an extra verification.

  • 0
Posted
1 hour ago, HyperBlown said:

If I remember correctly, this bug used to work on old Interlude versions using PHX. Where you request to learn an skill, but in reality you send other skill through phx. Put there a check to verify if that skill that is beeing added belongs to that class. If not, simply ignore. If you want to use that method you specified, use it more times on teleport, certain actions, enter/leave zone... Although its not an fix but rather an shortcut to dealing with your problem.

ya i remember old times, when i learned some skill after i took from phx packet, changed some numbers and learned new different skill 

  • Haha 1
  • 0
Posted (edited)
1 hour ago, dextroy said:

 

I appreciate that, but being honest i still couldn't understand what my next steps should be. Tracing the code could literally be looking into every single .java file, and as i said, i'm not a programmer/developer.

 

That's why i've been asking as least for a countermeasure, if someone is sending illegal packets that i can't track (i don't know how or it'd require too much programming knowlege), wouldn't a block on it's effects at least partially solve the issue?

 

I still don't know where to look at. If you could pinpoint something like: "You can add some code lines on WhateverFile.java and it will verify the skills" and somewhat of what the code would look like, then i can attempt a solution here.

 

But i'm not at advanced knowledge with java. Tracing everything, check packets, hacking, those are not things i'm experenced at, so i just honestly don't know where to start looking. With the information i'm receiving.

 

Zake told me to look on RequestAquireSkill.java and i was able to put an extra code line there. But i don't know if that's enough or where else i could put an extra verification.

As I mentioned, You need to verify if the requested skill to learn exists in the List of learnable skills from the current class the character is in.  

Something like this would do. 
(taking in consideration that this here below has indeed the "allowed" ids per class)
 

SkillTreeTable.getInstance().getAllowedSkills(getClassId())

Then on your learn skill method or even on the RequestAquireSkill you could put something like this.
 

if(SkillTreeTable.getInstance().getAllowedSkills(activeChar.getClassId()).stream().noneMatch(e->e.getId == _skillId))
    return;

Again, if this method does what it should do by its name, this if will check if the requested skillId exists on the allowed skill list for the current class of the character. If the requested Id doesnt exist, it will simply ignore.
But this is a very simple test, ideally you would want to check on level too since some classes can have the same skill but are capped on different levels. 

 

Edited by HyperBlown
  • 0
Posted
43 minutes ago, HyperBlown said:

As I mentioned, You need to verify if the requested skill to learn exists in the List of learnable skills from the current class the character is in.  

Something like this would do. 
(taking in consideration that this here below has indeed the "allowed" ids per class)
 

SkillTreeTable.getInstance().getAllowedSkills(getClassId())

Then on your learn skill method or even on the RequestAquireSkill you could put something like this.
 

if(SkillTreeTable.getInstance().getAllowedSkills(activeChar.getClassId()).stream().noneMatch(e->e.getId == _skillId))
    return;

 

Again, if this method does what it should do by its name, this if will check if the requested skillId exists on the allowed skill list for the current class of the character. If the requested Id doesnt exist, it will simply ignore.
But this is a very simple test, ideally you would want to check on level too since some classes can have the same skill but are capped on different levels. 

 

In order for me to understand, isn't the "Allowed Skills" list the skill tree sql table? If so, as i mentioned the skill tree only marks skills up to 1430. I don't get how they'd see any different. Here, i found the get allowed skills on the following java files:

image.png.86027caeb113e9bde8f2fecdc972eeef.png

 

Would it be on the L2PcInstance then? Here's the bit marked:

	/**
	 * check player skills and remove unlegit ones (excludes hero, noblesse and cursed weapon skills).
	 */
	public void checkAllowedSkills()
	{
		boolean foundskill = false;
		if (!isGM())
		{
			Collection<L2SkillLearn> skillTree = SkillTreeTable.getInstance().getAllowedSkills(getClassId());
			// loop through all skills of player
			for (final L2Skill skill : getAllSkills())
			{
				final int skillid = skill.getId();
				// int skilllevel = skill.getLevel();
				
				foundskill = false;
				// loop through all skills in players skilltree
				for (final L2SkillLearn temp : skillTree)
				{
					// if the skill was found and the level is possible to obtain for his class everything is ok
					if (temp.getId() == skillid)
					{
						foundskill = true;
					}
				}
				
				// exclude noble skills
				if (isNoble() && skillid >= 325 && skillid <= 397)
				{
					foundskill = true;
				}
				
				if (isNoble() && skillid >= 1323 && skillid <= 1327)
				{
					foundskill = true;
				}
				
				// exclude hero skills
				if (isHero() && skillid >= 395 && skillid <= 396)
				{
					foundskill = true;
				}
				
				if (isHero() && skillid >= 1374 && skillid <= 1376)
				{
					foundskill = true;
				}
				
				// exclude cursed weapon skills
				if (isCursedWeaponEquiped() && skillid == CursedWeaponsManager.getInstance().getCursedWeapon(_cursedWeaponEquipedId).getSkillId())
				{
					foundskill = true;
				}
				
				// exclude clan skills
				if (getClan() != null && skillid >= 370 && skillid <= 391)
				{
					foundskill = true;
				}
				
				// exclude seal of ruler / build siege hq
				if (getClan() != null && (skillid == 246 || skillid == 247))
					if (getClan().getLeaderId() == getObjectId())
					{
						foundskill = true;
					}
				
				// exclude fishing skills and common skills + dwarfen craft
				if (skillid >= 1312 && skillid <= 1322)
				{
					foundskill = true;
				}
				
				if (skillid >= 1368 && skillid <= 1373)
				{
					foundskill = true;
				}
				
				// exclude sa / enchant bonus / penality etc. skills
				if (skillid >= 3000 && skillid < 7000)
				{
					removeSkill(skill);
					LOGGER.warn("Character " + getName() + " of Account " + getAccountName() + " got skill " + skill.getName() + ".. Removed!"/* + IllegalPlayerAction.PUNISH_KICK */);
					foundskill = true;
				}
				
				// exclude Skills from AllowedSkills in options.properties
				if (Config.ALLOWED_SKILLS_LIST.contains(skillid))
				{
					foundskill = true;
				}
				
				// exclude Donator character
				if (isDonator())
				{
					foundskill = true;
				}
				
				// exclude Aio character
				if (isAio())
				{
					foundskill = true;
				}
				
				// remove skill and do a lil LOGGER message
				if (!foundskill)
				{
					removeSkill(skill);
					
					if (Config.DEBUG)
					{
						// sendMessage("Skill " + skill.getName() + " removed and gm informed!");
						LOGGER.warn("Character " + getName() + " of Account " + getAccountName() + " got skill " + skill.getName() + ".. Removed!"/* + IllegalPlayerAction.PUNISH_KICK */);
						
					}
				}
			}
			
			// Update skill list
			sendSkillList();
			
			skillTree = null;
		}
	}

 

How would i insert your code there? I tried but got some errors, so, i'm sending the source code and trying to understand the code's logic.

image.png.860fb30fe6ced257da045dd5e5772c2f.png

  • 0
Posted
6 minutes ago, dextroy said:

In order for me to understand, isn't the "Allowed Skills" list the skill tree sql table? If so, as i mentioned the skill tree only marks skills up to 1430. I don't get how they'd see any different. Here, i found the get allowed skills on the following java files:

image.png.86027caeb113e9bde8f2fecdc972eeef.png

 

Would it be on the L2PcInstance then? Here's the bit marked:

	/**
	 * check player skills and remove unlegit ones (excludes hero, noblesse and cursed weapon skills).
	 */
	public void checkAllowedSkills()
	{
		boolean foundskill = false;
		if (!isGM())
		{
			Collection<L2SkillLearn> skillTree = SkillTreeTable.getInstance().getAllowedSkills(getClassId());
			// loop through all skills of player
			for (final L2Skill skill : getAllSkills())
			{
				final int skillid = skill.getId();
				// int skilllevel = skill.getLevel();
				
				foundskill = false;
				// loop through all skills in players skilltree
				for (final L2SkillLearn temp : skillTree)
				{
					// if the skill was found and the level is possible to obtain for his class everything is ok
					if (temp.getId() == skillid)
					{
						foundskill = true;
					}
				}
				
				// exclude noble skills
				if (isNoble() && skillid >= 325 && skillid <= 397)
				{
					foundskill = true;
				}
				
				if (isNoble() && skillid >= 1323 && skillid <= 1327)
				{
					foundskill = true;
				}
				
				// exclude hero skills
				if (isHero() && skillid >= 395 && skillid <= 396)
				{
					foundskill = true;
				}
				
				if (isHero() && skillid >= 1374 && skillid <= 1376)
				{
					foundskill = true;
				}
				
				// exclude cursed weapon skills
				if (isCursedWeaponEquiped() && skillid == CursedWeaponsManager.getInstance().getCursedWeapon(_cursedWeaponEquipedId).getSkillId())
				{
					foundskill = true;
				}
				
				// exclude clan skills
				if (getClan() != null && skillid >= 370 && skillid <= 391)
				{
					foundskill = true;
				}
				
				// exclude seal of ruler / build siege hq
				if (getClan() != null && (skillid == 246 || skillid == 247))
					if (getClan().getLeaderId() == getObjectId())
					{
						foundskill = true;
					}
				
				// exclude fishing skills and common skills + dwarfen craft
				if (skillid >= 1312 && skillid <= 1322)
				{
					foundskill = true;
				}
				
				if (skillid >= 1368 && skillid <= 1373)
				{
					foundskill = true;
				}
				
				// exclude sa / enchant bonus / penality etc. skills
				if (skillid >= 3000 && skillid < 7000)
				{
					removeSkill(skill);
					LOGGER.warn("Character " + getName() + " of Account " + getAccountName() + " got skill " + skill.getName() + ".. Removed!"/* + IllegalPlayerAction.PUNISH_KICK */);
					foundskill = true;
				}
				
				// exclude Skills from AllowedSkills in options.properties
				if (Config.ALLOWED_SKILLS_LIST.contains(skillid))
				{
					foundskill = true;
				}
				
				// exclude Donator character
				if (isDonator())
				{
					foundskill = true;
				}
				
				// exclude Aio character
				if (isAio())
				{
					foundskill = true;
				}
				
				// remove skill and do a lil LOGGER message
				if (!foundskill)
				{
					removeSkill(skill);
					
					if (Config.DEBUG)
					{
						// sendMessage("Skill " + skill.getName() + " removed and gm informed!");
						LOGGER.warn("Character " + getName() + " of Account " + getAccountName() + " got skill " + skill.getName() + ".. Removed!"/* + IllegalPlayerAction.PUNISH_KICK */);
						
					}
				}
			}
			
			// Update skill list
			sendSkillList();
			
			skillTree = null;
		}
	}

 

How would i insert your code there? I tried but got some errors, so, i'm sending the source code and trying to understand the code's logic.

image.png.860fb30fe6ced257da045dd5e5772c2f.png

checkAllowedSkills is a method that runs when logging on the character. So after logging in, it will be ignored and people can do their bug. Thats why I said to put the verification on the place where u add the skill to the character.

  • 0
Posted
54 minutes ago, HyperBlown said:

checkAllowedSkills is a method that runs when logging on the character. So after logging in, it will be ignored and people can do their bug. Thats why I said to put the verification on the place where u add the skill to the character.

 

Ok, so the RequestAquireSkill.java. I'll send below what i did and the full code aswell:

image.png.f30b093e40b620240ca6cf0cc3a60a50.png

 

The first line is the 'If' you've suggested, but as you can see, there's an incompatibility with that "Lambda expression". What can i replace it with?

 

The second if is the skill_id verification i implemented, and it appears to be working on skill masters (i tested with < 1500 and it didn't allow me to learn the skill)

 

 

Here's the full code:

/*
 * L2jFrozen Project - www.l2jfrozen.com 
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package com.l2jfrozen.gameserver.network.clientpackets;

import org.apache.log4j.Logger;

import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.datatables.SkillTable;
import com.l2jfrozen.gameserver.datatables.sql.SkillSpellbookTable;
import com.l2jfrozen.gameserver.datatables.sql.SkillTreeTable;
import com.l2jfrozen.gameserver.model.L2PledgeSkillLearn;
import com.l2jfrozen.gameserver.model.L2ShortCut;
import com.l2jfrozen.gameserver.model.L2Skill;
import com.l2jfrozen.gameserver.model.L2SkillLearn;
import com.l2jfrozen.gameserver.model.actor.instance.L2FishermanInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2FolkInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2ItemInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2VillageMasterInstance;
import com.l2jfrozen.gameserver.network.SystemMessageId;
import com.l2jfrozen.gameserver.network.serverpackets.ExStorageMaxCount;
import com.l2jfrozen.gameserver.network.serverpackets.PledgeSkillList;
import com.l2jfrozen.gameserver.network.serverpackets.ShortCutRegister;
import com.l2jfrozen.gameserver.network.serverpackets.StatusUpdate;
import com.l2jfrozen.gameserver.network.serverpackets.SystemMessage;
import com.l2jfrozen.gameserver.util.IllegalPlayerAction;
import com.l2jfrozen.gameserver.util.Util;

public class RequestAquireSkill extends L2GameClientPacket
{
	private static Logger LOGGER = Logger.getLogger(RequestAquireSkill.class);
	
	private int _id;
	
	private int _level;
	
	private int _skillType;
	
	@Override
	protected void readImpl()
	{
		_id = readD();
		_level = readD();
		_skillType = readD();
	}
	
	@Override
	protected void runImpl()
	{
		
		final L2PcInstance player = getClient().getActiveChar();
		
		if (player == null)
			return;
		
		final L2FolkInstance trainer = player.getLastFolkNPC();
		
		if (trainer == null)
			return;
		
		final int npcid = trainer.getNpcId();
		
		if (!player.isInsideRadius(trainer, L2NpcInstance.INTERACTION_DISTANCE, false, false) && !player.isGM())
			return;
		
		if (!Config.ALT_GAME_SKILL_LEARN)
		{
			player.setSkillLearningClassId(player.getClassId());
		}
		
		if (player.getSkillLevel(_id) >= _level)
			// already knows the skill with this level
			return;
		
		if(SkillTreeTable.getInstance().getAllowedSkills(player.getClassId()).stream().noneMatch(e->e.getId == _skillId))
			return;
		
		// test block sills 1500+
		if ((_id) > 1500)
		{
			player.sendMessage("You are trying to learn an illegal skill");
			Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
			// illegal skill
			return;
		}
		
		final L2Skill skill = SkillTable.getInstance().getInfo(_id, _level);
		
		int counts = 0;
		int _requiredSp = 10000000;
		
		if (_skillType == 0)
		{
			
			final L2SkillLearn[] skills = SkillTreeTable.getInstance().getAvailableSkills(player, player.getSkillLearningClassId());
			
			for (final L2SkillLearn s : skills)
			{
				final L2Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
				if (sk == null || sk != skill || !sk.getCanLearn(player.getSkillLearningClassId()) || !sk.canTeachBy(npcid))
				{
					continue;
				}
				counts++;
				_requiredSp = SkillTreeTable.getInstance().getSkillCost(player, skill);
			}
			
			if (counts == 0 && !Config.ALT_GAME_SKILL_LEARN)
			{
				player.sendMessage("You are trying to learn skill that u can't..");
				Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
				return;
			}
			
			if (player.getSp() >= _requiredSp)
			{
				int spbId = -1;
				// divine inspiration require book for each level
				if (Config.DIVINE_SP_BOOK_NEEDED && skill.getId() == L2Skill.SKILL_DIVINE_INSPIRATION)
				{
					spbId = SkillSpellbookTable.getInstance().getBookForSkill(skill, _level);
				}
				else if (Config.SP_BOOK_NEEDED && skill.getLevel() == 1)
				{
					spbId = SkillSpellbookTable.getInstance().getBookForSkill(skill);
				}
				
				// spellbook required
				if (spbId > -1)
				{
					final L2ItemInstance spb = player.getInventory().getItemByItemId(spbId);
					
					if (spb == null)
					{
						// Haven't spellbook
						player.sendPacket(new SystemMessage(SystemMessageId.ITEM_MISSING_TO_LEARN_SKILL));
						return;
					}
					
					// ok
					player.destroyItem("Consume", spb, trainer, true);
				}
			}
			else
			{
				final SystemMessage sm = new SystemMessage(SystemMessageId.NOT_ENOUGH_SP_TO_LEARN_SKILL);
				player.sendPacket(sm);
				
				return;
			}
		}
		else if (_skillType == 1)
		{
			int costid = 0;
			int costcount = 0;
			// Skill Learn bug Fix
			final L2SkillLearn[] skillsc = SkillTreeTable.getInstance().getAvailableSkills(player);
			
			for (final L2SkillLearn s : skillsc)
			{
				final L2Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
				
				if (sk == null || sk != skill)
				{
					continue;
				}
				
				counts++;
				costid = s.getIdCost();
				costcount = s.getCostCount();
				_requiredSp = s.getSpCost();
			}
			
			if (counts == 0)
			{
				player.sendMessage("You are trying to learn skill that u can't..");
				Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
				return;
			}
			
			if (player.getSp() >= _requiredSp)
			{
				if (!player.destroyItemByItemId("Consume", costid, costcount, trainer, false))
				{
					// Haven't spellbook
					player.sendPacket(new SystemMessage(SystemMessageId.ITEM_MISSING_TO_LEARN_SKILL));
					return;
				}
				
				final SystemMessage sm = new SystemMessage(SystemMessageId.DISSAPEARED_ITEM);
				sm.addNumber(costcount);
				sm.addItemName(costid);
				sendPacket(sm);
			}
			else
			{
				final SystemMessage sm = new SystemMessage(SystemMessageId.NOT_ENOUGH_SP_TO_LEARN_SKILL);
				player.sendPacket(sm);
				return;
			}
		}
		else if (_skillType == 2) // pledgeskills TODO: Find appropriate system messages.
		{
			if (!player.isClanLeader())
			{
				// TODO: Find and add system msg
				player.sendMessage("This feature is available only for the clan leader");
				return;
			}
			
			int itemId = 0;
			int repCost = 100000000;
			// Skill Learn bug Fix
			final L2PledgeSkillLearn[] skills = SkillTreeTable.getInstance().getAvailablePledgeSkills(player);
			
			for (final L2PledgeSkillLearn s : skills)
			{
				final L2Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
				
				if (sk == null || sk != skill)
				{
					continue;
				}
				
				counts++;
				itemId = s.getItemId();
				repCost = s.getRepCost();
			}
			
			if (counts == 0)
			{
				player.sendMessage("You are trying to learn skill that u can't..");
				Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
				return;
			}
			
			if (player.getClan().getReputationScore() >= repCost)
			{
				if (Config.LIFE_CRYSTAL_NEEDED)
				{
					if (!player.destroyItemByItemId("Consume", itemId, 1, trainer, false))
					{
						// Haven't spellbook
						player.sendPacket(new SystemMessage(SystemMessageId.ITEM_MISSING_TO_LEARN_SKILL));
						return;
					}
					
					final SystemMessage sm = new SystemMessage(SystemMessageId.DISSAPEARED_ITEM);
					sm.addItemName(itemId);
					sm.addNumber(1);
					sendPacket(sm);
				}
			}
			else
			{
				final SystemMessage sm = new SystemMessage(SystemMessageId.ACQUIRE_SKILL_FAILED_BAD_CLAN_REP_SCORE);
				player.sendPacket(sm);
				return;
			}
			player.getClan().setReputationScore(player.getClan().getReputationScore() - repCost, true);
			player.getClan().addNewSkill(skill);
			
			if (Config.DEBUG)
			{
				LOGGER.debug("Learned pledge skill " + _id + " for " + _requiredSp + " SP.");
			}
			
			final SystemMessage cr = new SystemMessage(SystemMessageId.S1_DEDUCTED_FROM_CLAN_REP);
			cr.addNumber(repCost);
			player.sendPacket(cr);
			final SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_SKILL_S1_ADDED);
			sm.addSkillName(_id);
			player.sendPacket(sm);
			
			player.getClan().broadcastToOnlineMembers(new PledgeSkillList(player.getClan()));
			
			for (final L2PcInstance member : player.getClan().getOnlineMembers(""))
			{
				member.sendSkillList();
			}
			
			if (trainer instanceof L2VillageMasterInstance)
			{
				((L2VillageMasterInstance) trainer).showPledgeSkillList(player);
			}
			
			return;
		}
		
		else
		{
			LOGGER.warn("Recived Wrong Packet Data in Aquired Skill - unk1:" + _skillType);
			return;
		}
		
		player.addSkill(skill, true);
		
		if (Config.DEBUG)
		{
			LOGGER.debug("Learned skill " + _id + " for " + _requiredSp + " SP.");
		}
		
		player.setSp(player.getSp() - _requiredSp);
		
		final StatusUpdate su = new StatusUpdate(player.getObjectId());
		su.addAttribute(StatusUpdate.SP, player.getSp());
		player.sendPacket(su);
		
		final SystemMessage sp = new SystemMessage(SystemMessageId.SP_DECREASED_S1);
		sp.addNumber(_requiredSp);
		sendPacket(sp);
		
		final SystemMessage sm = new SystemMessage(SystemMessageId.LEARNED_SKILL_S1);
		sm.addSkillName(_id);
		player.sendPacket(sm);
		
		// update all the shortcuts to this skill
		if (_level > 1)
		{
			final L2ShortCut[] allShortCuts = player.getAllShortCuts();
			
			for (final L2ShortCut sc : allShortCuts)
			{
				if (sc.getId() == _id && sc.getType() == L2ShortCut.TYPE_SKILL)
				{
					final L2ShortCut newsc = new L2ShortCut(sc.getSlot(), sc.getPage(), sc.getType(), sc.getId(), _level, 1);
					player.sendPacket(new ShortCutRegister(newsc));
					player.registerShortCut(newsc);
				}
			}
		}
		
		if (trainer instanceof L2FishermanInstance)
		{
			((L2FishermanInstance) trainer).showSkillList(player);
		}
		else
		{
			trainer.showSkillList(player, player.getSkillLearningClassId());
		}
		
		if (_id >= 1368 && _id <= 1372) // if skill is expand sendpacket :)
		{
			final ExStorageMaxCount esmc = new ExStorageMaxCount(player);
			player.sendPacket(esmc);
		}
		
		player.sendSkillList();
	}
	
	@Override
	public String getType()
	{
		return "[C] 6C RequestAquireSkill";
	}
}

 

2 hours ago, AchYlek said:

ya i remember old times, when i learned some skill after i took from phx packet, changed some numbers and learned new different skill 

I'll Google it myself, but i'll just ask: do know a link to any tutorial on how to use this hack? This way i can use it myself to test if the fix worked.

  • 0
Posted
6 minutes ago, dextroy said:

 

Ok, so the RequestAquireSkill.java. I'll send below what i did and the full code aswell:

image.png.f30b093e40b620240ca6cf0cc3a60a50.png

 

The first line is the 'If' you've suggested, but as you can see, there's an incompatibility with that "Lambda expression". What can i replace it with?

 

The second if is the skill_id verification i implemented, and it appears to be working on skill masters (i tested with < 1500 and it didn't allow me to learn the skill)

 

 

Here's the full code:

/*
 * L2jFrozen Project - www.l2jfrozen.com 
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package com.l2jfrozen.gameserver.network.clientpackets;

import org.apache.log4j.Logger;

import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.datatables.SkillTable;
import com.l2jfrozen.gameserver.datatables.sql.SkillSpellbookTable;
import com.l2jfrozen.gameserver.datatables.sql.SkillTreeTable;
import com.l2jfrozen.gameserver.model.L2PledgeSkillLearn;
import com.l2jfrozen.gameserver.model.L2ShortCut;
import com.l2jfrozen.gameserver.model.L2Skill;
import com.l2jfrozen.gameserver.model.L2SkillLearn;
import com.l2jfrozen.gameserver.model.actor.instance.L2FishermanInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2FolkInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2ItemInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2VillageMasterInstance;
import com.l2jfrozen.gameserver.network.SystemMessageId;
import com.l2jfrozen.gameserver.network.serverpackets.ExStorageMaxCount;
import com.l2jfrozen.gameserver.network.serverpackets.PledgeSkillList;
import com.l2jfrozen.gameserver.network.serverpackets.ShortCutRegister;
import com.l2jfrozen.gameserver.network.serverpackets.StatusUpdate;
import com.l2jfrozen.gameserver.network.serverpackets.SystemMessage;
import com.l2jfrozen.gameserver.util.IllegalPlayerAction;
import com.l2jfrozen.gameserver.util.Util;

public class RequestAquireSkill extends L2GameClientPacket
{
	private static Logger LOGGER = Logger.getLogger(RequestAquireSkill.class);
	
	private int _id;
	
	private int _level;
	
	private int _skillType;
	
	@Override
	protected void readImpl()
	{
		_id = readD();
		_level = readD();
		_skillType = readD();
	}
	
	@Override
	protected void runImpl()
	{
		
		final L2PcInstance player = getClient().getActiveChar();
		
		if (player == null)
			return;
		
		final L2FolkInstance trainer = player.getLastFolkNPC();
		
		if (trainer == null)
			return;
		
		final int npcid = trainer.getNpcId();
		
		if (!player.isInsideRadius(trainer, L2NpcInstance.INTERACTION_DISTANCE, false, false) && !player.isGM())
			return;
		
		if (!Config.ALT_GAME_SKILL_LEARN)
		{
			player.setSkillLearningClassId(player.getClassId());
		}
		
		if (player.getSkillLevel(_id) >= _level)
			// already knows the skill with this level
			return;
		
		if(SkillTreeTable.getInstance().getAllowedSkills(player.getClassId()).stream().noneMatch(e->e.getId == _skillId))
			return;
		
		// test block sills 1500+
		if ((_id) > 1500)
		{
			player.sendMessage("You are trying to learn an illegal skill");
			Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
			// illegal skill
			return;
		}
		
		final L2Skill skill = SkillTable.getInstance().getInfo(_id, _level);
		
		int counts = 0;
		int _requiredSp = 10000000;
		
		if (_skillType == 0)
		{
			
			final L2SkillLearn[] skills = SkillTreeTable.getInstance().getAvailableSkills(player, player.getSkillLearningClassId());
			
			for (final L2SkillLearn s : skills)
			{
				final L2Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
				if (sk == null || sk != skill || !sk.getCanLearn(player.getSkillLearningClassId()) || !sk.canTeachBy(npcid))
				{
					continue;
				}
				counts++;
				_requiredSp = SkillTreeTable.getInstance().getSkillCost(player, skill);
			}
			
			if (counts == 0 && !Config.ALT_GAME_SKILL_LEARN)
			{
				player.sendMessage("You are trying to learn skill that u can't..");
				Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
				return;
			}
			
			if (player.getSp() >= _requiredSp)
			{
				int spbId = -1;
				// divine inspiration require book for each level
				if (Config.DIVINE_SP_BOOK_NEEDED && skill.getId() == L2Skill.SKILL_DIVINE_INSPIRATION)
				{
					spbId = SkillSpellbookTable.getInstance().getBookForSkill(skill, _level);
				}
				else if (Config.SP_BOOK_NEEDED && skill.getLevel() == 1)
				{
					spbId = SkillSpellbookTable.getInstance().getBookForSkill(skill);
				}
				
				// spellbook required
				if (spbId > -1)
				{
					final L2ItemInstance spb = player.getInventory().getItemByItemId(spbId);
					
					if (spb == null)
					{
						// Haven't spellbook
						player.sendPacket(new SystemMessage(SystemMessageId.ITEM_MISSING_TO_LEARN_SKILL));
						return;
					}
					
					// ok
					player.destroyItem("Consume", spb, trainer, true);
				}
			}
			else
			{
				final SystemMessage sm = new SystemMessage(SystemMessageId.NOT_ENOUGH_SP_TO_LEARN_SKILL);
				player.sendPacket(sm);
				
				return;
			}
		}
		else if (_skillType == 1)
		{
			int costid = 0;
			int costcount = 0;
			// Skill Learn bug Fix
			final L2SkillLearn[] skillsc = SkillTreeTable.getInstance().getAvailableSkills(player);
			
			for (final L2SkillLearn s : skillsc)
			{
				final L2Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
				
				if (sk == null || sk != skill)
				{
					continue;
				}
				
				counts++;
				costid = s.getIdCost();
				costcount = s.getCostCount();
				_requiredSp = s.getSpCost();
			}
			
			if (counts == 0)
			{
				player.sendMessage("You are trying to learn skill that u can't..");
				Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
				return;
			}
			
			if (player.getSp() >= _requiredSp)
			{
				if (!player.destroyItemByItemId("Consume", costid, costcount, trainer, false))
				{
					// Haven't spellbook
					player.sendPacket(new SystemMessage(SystemMessageId.ITEM_MISSING_TO_LEARN_SKILL));
					return;
				}
				
				final SystemMessage sm = new SystemMessage(SystemMessageId.DISSAPEARED_ITEM);
				sm.addNumber(costcount);
				sm.addItemName(costid);
				sendPacket(sm);
			}
			else
			{
				final SystemMessage sm = new SystemMessage(SystemMessageId.NOT_ENOUGH_SP_TO_LEARN_SKILL);
				player.sendPacket(sm);
				return;
			}
		}
		else if (_skillType == 2) // pledgeskills TODO: Find appropriate system messages.
		{
			if (!player.isClanLeader())
			{
				// TODO: Find and add system msg
				player.sendMessage("This feature is available only for the clan leader");
				return;
			}
			
			int itemId = 0;
			int repCost = 100000000;
			// Skill Learn bug Fix
			final L2PledgeSkillLearn[] skills = SkillTreeTable.getInstance().getAvailablePledgeSkills(player);
			
			for (final L2PledgeSkillLearn s : skills)
			{
				final L2Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
				
				if (sk == null || sk != skill)
				{
					continue;
				}
				
				counts++;
				itemId = s.getItemId();
				repCost = s.getRepCost();
			}
			
			if (counts == 0)
			{
				player.sendMessage("You are trying to learn skill that u can't..");
				Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
				return;
			}
			
			if (player.getClan().getReputationScore() >= repCost)
			{
				if (Config.LIFE_CRYSTAL_NEEDED)
				{
					if (!player.destroyItemByItemId("Consume", itemId, 1, trainer, false))
					{
						// Haven't spellbook
						player.sendPacket(new SystemMessage(SystemMessageId.ITEM_MISSING_TO_LEARN_SKILL));
						return;
					}
					
					final SystemMessage sm = new SystemMessage(SystemMessageId.DISSAPEARED_ITEM);
					sm.addItemName(itemId);
					sm.addNumber(1);
					sendPacket(sm);
				}
			}
			else
			{
				final SystemMessage sm = new SystemMessage(SystemMessageId.ACQUIRE_SKILL_FAILED_BAD_CLAN_REP_SCORE);
				player.sendPacket(sm);
				return;
			}
			player.getClan().setReputationScore(player.getClan().getReputationScore() - repCost, true);
			player.getClan().addNewSkill(skill);
			
			if (Config.DEBUG)
			{
				LOGGER.debug("Learned pledge skill " + _id + " for " + _requiredSp + " SP.");
			}
			
			final SystemMessage cr = new SystemMessage(SystemMessageId.S1_DEDUCTED_FROM_CLAN_REP);
			cr.addNumber(repCost);
			player.sendPacket(cr);
			final SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_SKILL_S1_ADDED);
			sm.addSkillName(_id);
			player.sendPacket(sm);
			
			player.getClan().broadcastToOnlineMembers(new PledgeSkillList(player.getClan()));
			
			for (final L2PcInstance member : player.getClan().getOnlineMembers(""))
			{
				member.sendSkillList();
			}
			
			if (trainer instanceof L2VillageMasterInstance)
			{
				((L2VillageMasterInstance) trainer).showPledgeSkillList(player);
			}
			
			return;
		}
		
		else
		{
			LOGGER.warn("Recived Wrong Packet Data in Aquired Skill - unk1:" + _skillType);
			return;
		}
		
		player.addSkill(skill, true);
		
		if (Config.DEBUG)
		{
			LOGGER.debug("Learned skill " + _id + " for " + _requiredSp + " SP.");
		}
		
		player.setSp(player.getSp() - _requiredSp);
		
		final StatusUpdate su = new StatusUpdate(player.getObjectId());
		su.addAttribute(StatusUpdate.SP, player.getSp());
		player.sendPacket(su);
		
		final SystemMessage sp = new SystemMessage(SystemMessageId.SP_DECREASED_S1);
		sp.addNumber(_requiredSp);
		sendPacket(sp);
		
		final SystemMessage sm = new SystemMessage(SystemMessageId.LEARNED_SKILL_S1);
		sm.addSkillName(_id);
		player.sendPacket(sm);
		
		// update all the shortcuts to this skill
		if (_level > 1)
		{
			final L2ShortCut[] allShortCuts = player.getAllShortCuts();
			
			for (final L2ShortCut sc : allShortCuts)
			{
				if (sc.getId() == _id && sc.getType() == L2ShortCut.TYPE_SKILL)
				{
					final L2ShortCut newsc = new L2ShortCut(sc.getSlot(), sc.getPage(), sc.getType(), sc.getId(), _level, 1);
					player.sendPacket(new ShortCutRegister(newsc));
					player.registerShortCut(newsc);
				}
			}
		}
		
		if (trainer instanceof L2FishermanInstance)
		{
			((L2FishermanInstance) trainer).showSkillList(player);
		}
		else
		{
			trainer.showSkillList(player, player.getSkillLearningClassId());
		}
		
		if (_id >= 1368 && _id <= 1372) // if skill is expand sendpacket :)
		{
			final ExStorageMaxCount esmc = new ExStorageMaxCount(player);
			player.sendPacket(esmc);
		}
		
		player.sendSkillList();
	}
	
	@Override
	public String getType()
	{
		return "[C] 6C RequestAquireSkill";
	}
}

 

I'll Google it myself, but i'll just ask: do know a link to any tutorial on how to use this hack? This way i can use it myself to test if the fix worked.

change _skillId to 

_id
  • 0
Posted
7 minutes ago, HyperBlown said:

change _skillId to 

_id

There's still an issue, possibly with the e->e due to the java version. Can i replace that with something else?

image.png.1e7ed9a9f9bffe9e9f16d31e54a26837.png

  • 0
Posted (edited)
17 minutes ago, dextroy said:

There's still an issue, possibly with the e->e due to the java version. Can i replace that with something else?

image.png.1e7ed9a9f9bffe9e9f16d31e54a26837.png

oh. you are using java 7 I assume?
then change it to this:

boolean foundSkill = false;            
        for(L2SkillLearn skillLearn : SkillTreeTable.getInstance().getAllowedSkills(player.getClassId())){
            if(skillLearn.getId() == _Id){
                foundSkill = true;
                break;
            }
        }
        if(!foundSkill)
            return;

 

Edited by HyperBlown
  • 0
Posted
3 hours ago, dextroy said:

....

Apparently you can not understand some essential things. You need to follow some strategy to get the right results in a bug fix but I wont go further about it.

I would like to dwell on 2 things that you keep saying.

  • I am not a programmer
    • Pay someone to do all the things you can't do
  • It is a hack.
    • It's not. It all depends on what answer the server will give to the client.

 

Anyway

Your bug is obvious by reading the client packet RequestAquireSkill.java.

 

- if (counts == 0 && !Config.ALT_GAME_SKILL_LEARN)
+ if (counts == 0)
{
	player.sendMessage("You are trying to learn skill that u can't..");
	Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
	return;
}

 

If you just c/p the above code, then ive just lost 5 minutes of my life to write this post.

If you continue reading this, well, i feel better...

 

A basic communication:

You (player) double clicking on the npc. The corresponding html is appearing to your screen. Guess what, the client didn't know the html. Guess what, the server checked if you are dead, if you are paralized, if if if if, and finally the server decided which html you have to read. After that, the client just appearing that 'box'.

When you click on "learn skills", a list of some skills would appear. Guess what, the client doesnt know what skills you have to see. The server checked your class,your level, your state, your effects and 1000 other things. Finally, the server accepted your request and after the click of a skill, you are about to see another html which is describes all the clicked skill infos (sp,exp,book etc). Once you click on learn, guess what! The client can't know if you are capable to learn that skill! and instead of decide alone this hard task, is sending to the server 3 things. 1) id, 2) level, 3) type. Now the server is about mess arround and collect any possible information about your request like if you are 1 class (and if yes, what skills you are capable to learn), if you are gm and 1000 other 'if'. Once the server approves, it consumes from you the required materials (exp,sp etc) and the, it gives you the skills. So now, (and finally) , guess what .... Do you believe that anything of what i wrote, is a hack? No! The 'hacker' the only thing that he did was to send the packet of the (id,lvl,type) a bit different. Like different id and level. If the 'hacker' will finally learn that skill, where's the glitch? The server responded OK and the client welcomed this new skill!

 

Enough with the words. Lets see the code.

 

Ignoring some code on the beggining and stand on this:

 

if (_skillType == 0)
		{

 

Like some ppl mentioned before, frozen is a bad choice. Here for example, what the fuck is 0 ? No comments from the developer and you cant know that shit. In that case, i know. Its the regular skills that the player requests. So 1st of all, here is the right place to check.

 

Inside of that brackets we can see this code

final L2SkillLearn[] skills = SkillTreeTable.getInstance().getAvailableSkills(player, player.getSkillLearningClassId());

for (final L2SkillLearn s : skills)
{
	final L2Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
	if (sk == null || sk != skill || !sk.getCanLearn(player.getSkillLearningClassId()) || !sk.canTeachBy(npcid))
	{
		continue;
	}
	counts++;
	_requiredSp = SkillTreeTable.getInstance().getSkillCost(player, skill);
}

 

I know that its a bit hard for you to understand whats exactly in there, but there are some calculations and verifications in order to verify that the player can actually learn that skill. But hold on, whats the 

counts++;

thing? Is it counting the verified skills? Oh yeah. Lets move on! Lets print whats the value of that 'counts' variable! [ Compiling.... ]  [ Printing... ]   [  0  ]. The value is 0. Just because the super haste isn't registered at any class . So how the hell did he actually learned that skill? Lets see what comes next!

 

if (counts == 0 && !Config.ALT_GAME_SKILL_LEARN)
{
	player.sendMessage("You are trying to learn skill that u can't..");
	Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to learn skill that he can't!!!", IllegalPlayerAction.PUNISH_KICK);
	return;
}

 

Something bad is happening here. Lets expand it a bit.

if the counts are 0 (yes we are 0) and our config is false kick the player... Wait what?

if (counts == 0 and config == false) kick the player... Wait what?

The config is true!

 

 

Guess.... what.... This condition, would never be executed....

  • 0
Posted
16 minutes ago, HyperBlown said:

oh. you are using java 7 I assume?
then change it to this:

boolean foundSkill = false;            
        for(L2SkillLearn skillLearn : SkillTreeTable.getInstance().getAllowedSkills(player.getClassId())){
            if(skillLearn.getId() == _Id){
                foundSkill = true;
                break;
            }
        }
        if(!foundSkill)
            return;

 

Alright, in the meantime i was testing l2phx with my previous code. And it also seems like my protection worked. I used it's injection to learn Super Haste and got this:

image.png.1cb5a730babc51c9475260f18d17a7ec.png

So i'll use your code that fits plus the one i added previously. I guess this should fix this particular issue.

 

Additionally, would you know how i could make it create a simple log file, or add it's messages to the server log? This way i can keep up with players that are trying to exploit the server easily, because as of it is, there's no logs being generated, just kicking out.

Guest
This topic is now closed to further replies.

×
×
  • Create New...