Sql fix for 0 class hacking

Joined
May 28, 2006
Messages
247
Reaction score
32
As you may or may not know, there has been an exploit where first bypassing game guard (and we all know thats pretty easy by now) and setting your character class to 0 on newly created character you would crash the game server. Also its possible to set the face of your character to 0 resulting in a character without a head in game, as well as the famous creating mk chars on kr account and vice versa.

Have no fear, the solution is here.

I made a bit of modification to the stored procedure that is executed before data is inserted into database that will check such things and make them impossible.

I have attached the .sql file to this post, just run it in your db and it will patch up the stored procedure.

Note: This is made for 2240DB might need slight modification to work with older DB's and RYL1 but should be fairly simple to adjust.

Note2: At the moment it will just auto correct hacked values, but I'm planning on having it delete the entire account for the user trying to do this, cause we know that he have been hacking if this occurs and we really should punish him by deleting his entire account instead of just fixing his hacked values. But for now it will just auto correct.

Enjoy.
 

Attachments

Re: [Share] Sql fix for 0 class hacking

I was trying to fix the RYL1 dagger exploit in a similar fashion by running an SQL checker once a day looking for bad values in the inventory data.

I never got around to parsing a correct inventory though :/
 
Re: [Share] Sql fix for 0 class hacking

I was trying to fix the RYL1 dagger exploit in a similar fashion by running an SQL checker once a day looking for bad values in the inventory data.

I never got around to parsing a correct inventory though :/


-> Made by Alpha - Binary structure for equipment in DB

--

/* 7D1*6, 7D2*20
20 00 00 00 <--- data length
<------- serial --------> <-ID-> <- pos-> <count>
33 00 00 00 00 00 00 0C D2 07 12 00 0E 14
58 00 00 00 00 00 00 0C D1 07 22 00 0E 06
11 00 00 00 00 00 01 07 79 00 22 12 2C 64 00 00 20 C0 9B 00 F1 0F F2 0F C3 0F F4 0F F5 0F 56 00 F7 0F 58 00 F9 0F FA 0F FB 0F FC 0F
0x??ZYX?
0x0E0012
0x0E0022
0x2C1222
__^^____ = The length of this item line
_______^ = 1-Equip table, 2- inventory

==============================================================================================================================
80 00 00 00 <-- data length
<-------- serial ---------> <-ID-> <- pos-> <C> ?? ++ <-socks(1=ruby)>
73 00 00 00 00 00 00 0C A3 00 01 00 23 25 01 50 25 55 9B 00 01 01 01 01 01 03 15 25 06 06 04 D7 0B 9E 04
73 00 00 00 00 00 00 0C A3 00 01 00 1E 25 01 00 20 50 ED 00 <==============> 03 15 25 06 06 04 D7 0B 9E 04 <-- Elf Helm A++ grade
78 00 00 00 00 00 00 0C 0C 02 41 00 14 64 00 00 20 00 00 00 <-- Metal hand
74 00 00 00 00 00 00 0C 70 02 51 00 14 64 00 00 20 00 00 00 <-- Metal boots
20 00 00 00 00 00 00 00 41 06 91 00 14 64 00 00 20 00 00 00 <-- initial dagger
C0 00 00 00 00 00 00 0C 61 06 B1 00 22 0B 00 00 20 70 DB 00 D1 03 62 02 44 09 08 04 29 06 AA 05 EB 00 <-- Rune dagger A grade

Helm: def:354, evd:98, hp:3200, rec:189, mag:73
0x162 0x62 0xC80 0xBD 0x49

def=base+number.
hp,mp=50*number
dura=number+100 (rollover @ FF or 355 dura)
<NS> = Num of stats in list & S=Sockets in list(in use)
M = Max num of socks
++ = Enchantment level multiplied by 8. 50/8=lv 10
01 00 20 50 ED 00 03 15 25 06 06 04 D7 0B 9E 04
<-3-> <-5-> <-6-> <-7-> <-E->
150 62 40 BD 49
00 00 20 C0 9B 00 F1 0F F2 0F C3 0F F4 0F F5 0F 56 00 F7 0F 58 00 F9 0F FA 0F FB 0F FC 0F
M<NS><dura> <-1-> <-2-> <-3-> <-4-> <-5-> <-6-> <-7-> <-8-> <-9-> <-A-> <-B-> <-C-> <-D-> <-E->
max min def hit evd hp hp re mp mp re crit block speed mag mag res


73 00 00 00 00 00 00 0C A3 00 01 00 23 25 01 40 25 55 9B 00 01 01 01 01 01 03 15 25 06 06 04 D7 0B 9E 04

*/
 
Re: [Share] Sql fix for 0 class hacking

Didn't know that bug existed 0.o

GM STOL ME HAD!!!!!! fuk gm o0o!!!

Tyfix - Sql fix for 0 class hacking - RaGEZONE Forums
 
Re: [Share] Sql fix for 0 class hacking

tyfix bro , i got a question.
This is the binary i took from my Char's Equip ( i can read it's 2 item since there are 2 Data Length)

0x2C 00 00 00 E9 17 00 00 00 00 00 00 C9 00 11 00 14 64 00 00 20 00 00 00 EA 17 00 00 00 00 00 00 59 02 51 00 14 61 00 00 20 00 00 00


0x2C 00 00 00 <Data Length>
E9 17 00 00 00 00 00 00 <Serial number. Compare with Admintool , it's Reversed>
C9 00 <ID (ID in Itemscript?)>
11 <POS ( position like Armor slot \ weapon slot \ ring slot etc?)>
00 <??>
14 <requirement>
64 <Dubility>
00 00 <??>



20 00 00 00 <Data Length>
EA 17 00 00 00 00 00 00 <Seems like Reversed Serial number from Admintool>
59 02 <Reversed Hex Number( It's a Leather Boot (ID 601 [Hex 259])
51 <Position Boot Slot>
00
14 <Requirement 20>
61 <Dubility = 97>
00 00



I found the binary of the position which represent some slot
01 = <Helm slot>
11 = <Shirt>
21 = <Tunic>
31 = <>
41 = <Glove Slot>
51 = <Boot Slot>
61 = <>
71 = <>
81 = <>
91 = <Right Hand Weapon slot>
B1 = <Left Hand Weapon slot>

Correct me if i am wrong , bro :)

(how about this? -> 0x45000000E833000000000010B01301001E38000020501C0003080502E60177009E018E6100000000000CFC13310023440250255528000B0B0B0B0B933B2502161297023E01)
 
Last edited:
Re: [Share] Sql fix for 0 class hacking

first: wrong thread.
second: open rylDatabaseExtraChecks project

/// <summary>
/// Contains the definition of item type to available slots mapping
///
/// type = the item type which is given to it in itemscript
/// slots = array of slot ID's where the given type item can be placed
/// slot ID's (note the names are based on human equipment):
/// 0 - head
/// 1 - shirt
/// 2 - tunic
/// 3 - armor
/// 4 - gloves
/// 5 - shoes
/// 6 - necky
/// 7 - left ring
/// 8 - right ring
/// 9 - left weapon page 1
/// 10 - left weapon page 2
/// 11 - right weapon page 1
/// 12 - right weapon page 2
/// </summary>

3. in /gm portal func.inc.php :

PHP:
/////////////////// DATA MANIPULATION & SYNTAX /////////////////////
function getItem(&$binData){
	/* 7D1*6, 7D2*20
	20 00 00 00   <--- data length
	<------- serial -------->  <-ID-> <- pos-> <count>
	33 00 00 00   00 00 00 0C   D2 07 12 00 0E 14 
	58 00 00 00   00 00 00 0C   D1 07 22 00 0E 06 
	11 00 00 00   00 00 01 07   79 00 22 12 2C 64   00 00 20 C0 9B 00   F1 0F F2 0F   C3 0F F4 0F   F5 0F 56 00 F7 0F 58 00   F9 0F FA 0F   FB 0F FC 0F 
	0x??ZYX?
	0x0E0012
	0x0E0022
	0x2C1222
	__^^____ = The length of this item line
	_______^ = 1-Equip table, 2- inventory

    ==============================================================================================================================
	80 00 00 00   <-- data length
	<-------- serial ---------> <-ID->  <- pos-> <C>  ?? ++               <-socks(1=ruby)>
	73 00   00 00 00 00   00 0C A3 00   01 00 23 25   01 50 25 55   9B 00 01 01   01 01 01 03   15 25 06 06   04 D7 0B 9E   04
	73 00   00 00 00 00   00 0C A3 00   01 00 1E 25   01 00 20 50   ED 00 <==============> 03   15 25 06 06   04 D7 0B 9E   04 <-- Elf Helm A++ grade
	78 00   00 00 00 00   00 0C 0C 02   41 00 14 64   00 00 20 00   00 00 <-- Metal hand
	74 00   00 00 00 00   00 0C 70 02   51 00 14 64   00 00 20 00   00 00 <-- Metal boots
	20 00   00 00 00 00   00 00 41 06   91 00 14 64   00 00 20 00   00 00 <-- initial dagger
	C0 00   00 00 00 00   00 0C 61 06   B1 00 22 0B   00 00 20 70   DB 00 D1 03   62 02 44 09   08 04 29 06   AA 05 EB 00 <-- Rune dagger A grade
	
	Helm: def:354, evd:98, hp:3200, rec:189, mag:73
	        0x162    0x62    0xC80     0xBD    0x49
	        
	def=base+number.
	hp,mp=50*number
	dura=number+100 (rollover @ FF or 355 dura)
	<NS> = Num of stats in list & S=Sockets in list(in use)
	M = Max num of socks
	++ = Enchantment level multiplied by 8. 50/8=lv 10
	01 00 20 50 ED 00   03 15 25 06   06 04 D7 0B   9E 04
	                    <-3-> <-5->   <-6-> <-7->   <-E->
	                     150   62       40    BD      49
	00 00 20 C0 9B 00   F1 0F F2 0F   C3 0F F4 0F   F5 0F 56 00 F7 0F 58 00   F9 0F FA 0F   FB 0F FC 0F 
	       M<NS><dura>  <-1-> <-2->   <-3-> <-4->   <-5-> <-6-> <-7-> <-8->   <-9-> <-A->   <-B-> <-C->   <-D-> <-E->
	                    max   min     def   hit     evd   hp    hp re   mp    mp re  crit   block speed   mag   mag res

	
	73 00 00 00   00 00 00 0C   A3 00 01 00 23 25 01 40   25 55 9B 00   01 01 01 01   01 03 15 25 06 06 04 D7   0B 9E 04
	
	*/
	$bArr = bin2bytearr($binData);
	$out = array(); 
	$len = getUint32($bArr,0);
	if(count($bArr)!=$len){
		echo "<b>Field seems to be truncated to ".count($bArr).", has to be: ".$len."</b><br>";	
		return array();
	}
	for($i=4;$i<$len;){
		$rowLen=$bArr[$i+12];
		$socksA=array();
		$statsA=array();
		$EstatA=array();
		$s1=dechex(getUint32($bArr,$i+4));
		$s2=dechex(getUint32($bArr,$i));
		$s1="0x".str_repeat("0",(8-strlen($s1))).$s1;
		$s2=str_repeat("0",(8-strlen($s2))).$s2;
		$serial=$s1.$s2;
		$id = getUint16($bArr,$i+8);
		$count = $bArr[$i+13];
		$placed = dechex(getUint16($bArr,$i+10));
		$placed=str_repeat("0",(4-strlen($placed))).$placed;
		$z=hexdec(substr($placed,0,1));
		$y=hexdec(substr($placed,1,1));
		$x=hexdec(substr($placed,2,1));
		$t=hexdec(substr($placed,3,1));
		if($rowLen>0xE){ // Equipment
			$enchLvl = ($bArr[$i+15]/8);
			$socks = hexdec(substr(dechex($bArr[$i+16]),1));
			$tmp=dechex($bArr[$i+17]);
			$stats=hexdec(substr($tmp,0,1));
			$usedSocks = hexdec(substr($tmp,1));
			$dura=$bArr[$i+18]+100;
			if($dura>0xFF)$dura-=0x100;
			$p2=$i+20;
			for($sc=0;$sc<$usedSocks;$sc++){
				$socksA[]=$bArr[$p2];
				$p2++;
			}
			for($sc=0;$sc<$stats;$sc++){
				$s=dechex(getUint16($bArr,$p2));
				$s=str_repeat("0",(4-strlen($s))).$s;
				$nS=hexdec("0".substr($s,0,3));
				$nI=hexdec("0".substr($s,3));
				if($nI==6||$nI==8)$nS*=50;
				$statsA[$nI]=$nS;
				$p2+=2;
			}
			$EstatA=array($enchLvl,$dura,$socksA,$statsA,$socks);
		}
		$out[]=array($serial,$id,$t,$count,array($x,$y,$z),$EstatA);
		$i+=$rowLen; // move next item
	}
	return $out;
}
 
Re: [Share] Sql fix for 0 class hacking

thank you for the tip and sorry for the incorrect thread's question. alphabest. By the way , any tip for making a trigger which could check the slot whether it's inserted with incorrect item type? for example , We restrict all the slot beside [Left hand \ Right hand + Page 1\2] ,
1. We create a Weapons Table (Contains all the human weapon [ sword, dagger , axe , mace etc] with ID [ ID took from item script])
2. We create a trigger to check Iteminfo
- Check every slot which contained Item and classify them
- Determine whether weapons are slotted into an incorrect slot
- /// slots = array of slot ID's where the given type item can be placed
/// slot ID's (note the names are based on human equipment):
/// 0 - head
/// 1 - shirt
/// 2 - tunic
/// 3 - armor
/// 4 - gloves
/// 5 - shoes
/// 6 - necky
/// 7 - left ring
/// 8 - right ring
- If slot shown above Contain any Weapon ID then execute dbo.updateCharDeletion2 ( which wipe off the character's item)


Sorry bro if i am messed my question and i really appreciate your helps :)
 
Last edited:
Re: [Share] Sql fix for 0 class hacking

thats what rylDatabaseExtraChecks is meant for...
 
Re: [Share] Sql fix for 0 class hacking

thx bro , i know rylDatabaseExtraChecks is the best. but i cant implement it on window server 2000. i just willing to try another way which is SQL based. I am weak in coding SQL but i could learn if my idea is correct :) Can the func.inc.php straight away insert as a trigger ?
 
Re: [Share] Sql fix for 0 class hacking

Here I don't use this method, because don't know how use it =/ Have diferentes sql servers and others problems... But I created another type of check, what check every players what loggin in last 15 minutes and see if they inventory have anything wrong... It ban automatic, but dont disconect players... It isn't the best way, but work ..
 
Re: [Share] Sql fix for 0 class hacking

Here I don't use this method, because don't know how use it =/ Have diferentes sql servers and others problems... But I created another type of check, what check every players what loggin in last 15 minutes and see if they inventory have anything wrong... It ban automatic, but dont disconect players... It isn't the best way, but work ..

thats a problem if you ask me - what if a player actually accidently puts something out of place. point is the game client allows it and thru hacking is not the only way of getting the stream messed up. But yeah.. you dont have the old stream before the update, that means a poor guy who got lag got banned for nothing :P
 
Re: [Share] Sql fix for 0 class hacking

Code:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO




ALTER      PROCEDURE [dbo].[InsertChar]
@user_uid	AS INT,				/* 유저 고유 아이디			*/
@user_pos	AS INT,				/* 캐릭터 위치 (3개의 슬롯)		*/
@user_name	AS VARCHAR(16),			/* 캐릭터 이름				*/
@user_Sex	AS TINYINT,			/* 캐릭터 성				*/
@user_Hair	AS TINYINT,			/* 캐릭터 머리 모양			*/
@user_Face	AS TINYINT,			/* 캐릭터 얼굴 모양			*/
@user_Nation	AS TINYINT,			/* 캐릭터 국가				*/
@user_Class	AS SMALLINT,			/* 캐릭터 클래스			*/
@C_Gold		AS INT,				/* 캐릭터 소지금			*/					
@C_STR		AS SMALLINT,			/* 캐릭터 STR				*/
@C_DEX		AS SMALLINT,			/* 캐릭터 DEX				*/
@C_CON		AS SMALLINT,			/* 캐릭터 CON				*/
@C_INT		AS SMALLINT,			/* 캐릭터 INT				*/
@C_WIS		AS SMALLINT,			/* 캐릭터 WIS				*/
@PointX		AS REAL,			/* 캐릭터 Point X 좌표			*/
@PointY		AS REAL,			/* 캐릭터 Point Y 좌표			*/
@PointZ		AS REAL,			/* 캐릭터 Point Z 좌표			*/
@C_Equip	AS varBINARY(30),			/* 장비 (2 * 15 = 30)			*/
@Skill		AS varBinary(84),
@UserInfoType	TINYINT,
@CID		INT	OUTPUT
AS

SET NOCOUNT ON

--DECLARE @UID INT
DECLARE @C_HP INT, @C_MP INT

/* 캐릭터 이름 확인 */
SELECT @CID = CID FROM CharInfo WHERE Name = @user_name
IF @CID <> 0
BEGIN
	SET @CID = -1	/* 동일 이름 존재 */
	RETURN
END

/* 슬롯 확인 */
DECLARE @CharSlot INT
IF @user_pos = 0
BEGIN
	SELECT @CharSlot = Char1 FROM UserInfo WHERE UID = @user_uid AND OldServerGroupID = @UserInfoType
END
ELSE IF @user_pos = 1
BEGIN
	SELECT @CharSlot = Char2 FROM UserInfo WHERE UID = @user_uid AND OldServerGroupID = @UserInfoType
END
ELSE IF @user_pos = 2
BEGIN
	SELECT @CharSlot = Char3 FROM UserInfo WHERE UID = @user_uid AND OldServerGroupID = @UserInfoType
END
ELSE IF @user_pos = 3
BEGIN
	SELECT @CharSlot = Char4 FROM UserInfo WHERE UID = @user_uid AND OldServerGroupID = @UserInfoType
END
ELSE IF @user_pos = 4
BEGIN
	SELECT @CharSlot = Char5 FROM UserInfo WHERE UID = @user_uid AND OldServerGroupID = @UserInfoType
END

IF @CharSlot <> 0
BEGIN
	SET @CID =  -2	/* 슬롯이 차있음 */
	RETURN
END

-- Hacker check / fix
IF @user_Nation > 1
BEGIN
	SET @user_Nation = 1
END
ELSE IF @user_Nation < 0
BEGIN
	SET @user_Nation = 0
END

IF @user_Sex > 2
BEGIN
	SET @user_Sex = 2
END
ELSE IF @user_Sex < 1
BEGIN
	SET @user_Sex = 1
END

IF @user_Face > 7
BEGIN
	SET @user_Face = 7
END
ELSE IF @user_Face < 1
BEGIN
	SET @user_Face = 1
END

IF @user_Hair < 1
BEGIN
	SET @user_Hair = 1
END

IF @user_Nation = 0
BEGIN
	IF @user_Sex = 1
	BEGIN
		IF @user_Hair > 5
		BEGIN
			SET @user_Hair = 5
		END
	END
	ELSE IF @user_Hair > 7
	BEGIN
		SET @user_Hair = 7
	END

	IF @user_Class < 1
	BEGIN
		SET @user_Class = 1
	END
	ELSE IF @user_Class > 4
	BEGIN
		SET @user_Class = 4
	END
END
ELSE IF @user_Nation = 1
BEGIN
	IF @user_Hair > 7
	BEGIN
		SET @user_Hair = 7
	END
	IF @user_Class < 18
	BEGIN
		SET @user_Class = 18
	END
	ELSE IF @user_Class > 19
	BEGIN
		SET @user_Class = 19
	END
END

SET @C_HP = 100 + @C_CON * 8 + 2
IF @C_INT > @C_WIS
BEGIN
	SET @C_MP = 100 + @C_INT * 8 + 2
END
ELSE
BEGIN
	SET @C_MP = 100 + @C_WIS * 8 + 2
END

BEGIN TRAN

SELECT @CID = MAX(CID) + 1 FROM CharInfo WITH (UPDLOCK)

IF (@CID IS NULL)
	SET @CID = 1

INSERT INTO CharInfo (CID,Name, Sex, Hair, Face, Race, Class, Equip, Gold, STR, DEX, CON, Intell, WIS, HP, MP) 
VALUES (@CID,@user_name, @user_Sex, @user_Hair, @user_Face, @user_Nation, @user_Class, @C_Equip, @C_Gold, @C_STR, @C_DEX, @C_CON, @C_INT, @C_WIS, @C_HP, @C_MP)

IF @@ERROR <> 0
BEGIN
	ROLLBACK TRAN
	SET @CID =  -100
	RETURN
END

COMMIT TRAN

INSERT INTO CharInfoEx (CID) VALUES (@CID)

INSERT INTO CharItem (CID) VALUES (@CID)
INSERT INTO CharItemEx (CID) VALUES (@CID)

INSERT INTO CharSkill (CID, Skill) VALUES (@CID, @Skill)

INSERT INTO CharSpell (CID) VALUES (@CID)

INSERT INTO CharPos (CID, LastPointX, LastPointY, LastPointZ, SavePointX, SavePointY, SavePointZ) VALUES (@CID, @PointX, @PointY, @PointZ, @PointX, @PointY, @PointZ)

INSERT INTO CharInfo_Time(CID,CreateTime,UpdateTime)
VALUES (@CID,GETDATE(),GETDATE())

INSERT INTO Friend (CID) VALUES (@CID)
INSERT INTO Quest (CID) VALUES (@CID)

-- UnifiedCharList정보테이블에 입력하기
INSERT TblUnifiedCharList(UID,OldServerGroupID,BeforeCID,NewCID,BeforeCharName)
VALUES (@user_uid,@UserInfoType,@CID,@CID,@user_name)


/* 유저 정보 테이블 업데이트 */
EXEC UpdateCharUID @user_uid, @user_pos, @CID , @UserInfoType

so this SQL work right ?
work on mssql 2000 ?
 
Back