Char Overwrite Duping. Possible Fix?

01/07/2019 00:19 Naltalah#1
Hi there.

I tried to fix the Char Overwrite bug today, kinda not successful. A player told me there are two ways of doing it:
Logging in a deleted character and just creating a new one at a certain slot, done via CE.

So far I've managed to block deleted characters.
When it comes to just creating a new character, the already released fixes don't seem to work for this.

I've googled a bit and found these SQL changes by Sedrika, Pumaa and Twilight:

Code:
BEGIN
			if exists(select playerslot from CHARACTER_TBL where account = lower(@iaccount) and playerslot = 0 and isblock = 'F')
			if exists(select playerslot from CHARACTER_TBL where account = lower(@iaccount) and playerslot = 1 and isblock = 'F')
			if exists(select playerslot from CHARACTER_TBL where account = lower(@iaccount) and playerslot = 2 and isblock = 'F')
  begin
   select fError = '0', fText = 'Slot taken!'
   return
  end
  
 declare  [MENTION=4037112]I1_[/MENTION]cnt int  
 select  [MENTION=4037112]I1_[/MENTION]cnt = count(*) from CHARACTER_TBL where account = @iaccount and isblock = 'F'  
 if  [MENTION=4037112]I1_[/MENTION]cnt > 2  
 begin  
  SELECT  fError = '0', fText = 'Too many chars!'   
  RETURN  
 end
For some reason, I still get fError = 1 when the player creates the character. From my understanding, it should check for the taken slot. However, it doesn't.

Another thing I came up with was:

Code:
  DECLARE [MENTION=303108]slot[/MENTION]counter int
  SELECT  [MENTION=303108]slot[/MENTION]counter = count(playerslot) from CHARACTER_TBL where account = lower(@iaccount) and playerslot =  [MENTION=2476276]iPlayer[/MENTION]slot and isblock ='F'
  if  [MENTION=303108]slot[/MENTION]counter != 0
  begin
	select fError = '2', fText = 'Slot taken!'
	return
  end
This kinda worked, but the player went afk, so I couldnt test his way of doing it.

I also tried doing something in the code, it's more or less the same check, I just wanted to make sure.

Code:
	sprintf(szQuery1337, "SELECT [isblock] FROM CHARACTER_01_DBF.dbo.CHARACTER_TBL WHERE [playerslot] = %d AND [isblock] = 'F' AND [account] = '%s'", nSlot, lpDbOverlappedPlus->AccountInfo.szAccount);
	if (FALSE == qry->Exec(szQuery1337))
	{
		WriteLog("%s, %d\r\n\t%s", __FILE__, __LINE__, szQuery1337);
		FreeRequest(lpDbOverlappedPlus);
		return;
	}
	if (qry->Fetch())
	{
		if (lpDbOverlappedPlus->AccountInfo.szAccount)
		{
			WriteLog("Duplication of Character found!");
			BanAccount(qry, lpDbOverlappedPlus, szAccName);
		}
	}
If I now go to the creation screen on my account, restore the deleted character in that slot via DB and try to create a character, I successfully get fError = 2.


Question: Are there more checks neccessary or can this be bypassed?

Thanks in advance.
01/07/2019 11:17 Dr. Peacock#2
There are other Tools like CE, if you want to bypass something, you can.
Knowledge is for Everything the Answere... (or money xD)
I can send you later a Database Include Fixxes if you want so, just Check it out, There are all known (Public) Dupe Fixxes Include, the Source Part of some Bad Coded Offi system parts you need to fix for Yourself.
01/07/2019 16:16 ZeroTwo02#3
In S8 section of CHARACTER_STR

Code:
			FROM CHARACTER_TBL A 
					inner join TASKBAR_TBL B on A.m_idPlayer   = B.m_idPlayer and A.serverindex  = B.serverindex
					inner join TASKBAR_ITEM_TBL C on B.m_idPlayer   = C.m_idPlayer and B.serverindex  = C.serverindex
					inner join INVENTORY_TBL D on C.m_idPlayer   = D.m_idPlayer and C.serverindex  = D.serverindex
					inner join SKILLINFLUENCE_TBL E on C.m_idPlayer   = E.m_idPlayer and C.serverindex  = E.serverindex
					inner join INVENTORY_EXT_TBL F on E.m_idPlayer   = F.m_idPlayer and E.serverindex  = F.serverindex
					left outer join GUILD_MEMBER_TBL G on E.serverindex = G.serverindex and E.m_idPlayer = G.m_idPlayer
					left outer join BILING_ITEM_TBL H on E.serverindex = H.serverindex and E.m_idPlayer = H.m_idPlayer
					left outer join tblRestPoint R on E.serverindex = R.serverindex and E.m_idPlayer = R.m_idPlayer
			WHERE A.m_idPlayer = @im_idPlayer
					AND A.serverindex =  [MENTION=3453071]iServe[/MENTION]rindex
					AND A.account = lower(@iaccount)
                                        -- fix
                                        AND A.isblock = 'F'
01/07/2019 16:59 Naltalah#4
Quote:
Originally Posted by ZeroTwo02 View Post
In S8 section of CHARACTER_STR

Code:
			FROM CHARACTER_TBL A 
					inner join TASKBAR_TBL B on A.m_idPlayer   = B.m_idPlayer and A.serverindex  = B.serverindex
					inner join TASKBAR_ITEM_TBL C on B.m_idPlayer   = C.m_idPlayer and B.serverindex  = C.serverindex
					inner join INVENTORY_TBL D on C.m_idPlayer   = D.m_idPlayer and C.serverindex  = D.serverindex
					inner join SKILLINFLUENCE_TBL E on C.m_idPlayer   = E.m_idPlayer and C.serverindex  = E.serverindex
					inner join INVENTORY_EXT_TBL F on E.m_idPlayer   = F.m_idPlayer and E.serverindex  = F.serverindex
					left outer join GUILD_MEMBER_TBL G on E.serverindex = G.serverindex and E.m_idPlayer = G.m_idPlayer
					left outer join BILING_ITEM_TBL H on E.serverindex = H.serverindex and E.m_idPlayer = H.m_idPlayer
					left outer join tblRestPoint R on E.serverindex = R.serverindex and E.m_idPlayer = R.m_idPlayer
			WHERE A.m_idPlayer = @im_idPlayer
					AND A.serverindex =  [MENTION=3453071]iServe[/MENTION]rindex
					AND A.account = lower(@iaccount)
                                        -- fix
                                        AND A.isblock = 'F'
Already done that. As i said i fixed deleted characters Logging in. Thank you regardless for Sharing.
01/07/2019 17:53 ZeroTwo02#5
CDbManager::CreatePlayer

Change ->

Code:
	char szQuery[QUERY_SIZE]	= { 0,};
	DBQryCharacter( szQuery, "I1", 0, g_appInfo.dwSys, lpDbOverlappedPlus->AccountInfo.szAccount, lpDbOverlappedPlus->AccountInfo.szPlayer, nSlot, dwWorldID,
		dwIndex, vPos.x, vPos.y, vPos.z, '\0', nSkinSet, nHairMesh,	dwHairColor, nHeadMesh, nSex );

	if( FALSE == qry->Exec( szQuery ) )
	{
		WriteLog( "%s, %d\r\n\t%s", __FILE__, __LINE__, szQuery );
		FreeRequest( lpDbOverlappedPlus );
		return;
	}
Too ->

Code:
	char szQuery0[QUERY_SIZE] = { 0,};
	sprintf(szQuery0, "SELECT account FROM ACCOUNT_DBF.dbo.ACCOUNT_TBL WHERE account='%s' AND password='%s'", lpDbOverlappedPlus->AccountInfo.szAccount, lpDbOverlappedPlus->AccountInfo.szPassword);

	if( FALSE == qry->Exec( szQuery0 ) )
	{
		WriteLog( "%s, %d\r\n\t%s", __FILE__, __LINE__, szQuery0 );
		FreeRequest( lpDbOverlappedPlus );
		return;
	}

	if( !qry->Fetch() )
	{
		FreeRequest( lpDbOverlappedPlus );
		return;
	}

	char szQuery1[QUERY_SIZE]	= { 0,};
	
	sprintf( szQuery1, "SELECT account FROM CHARACTER_01_DBF.dbo.CHARACTER_TBL WHERE account='%s' AND playerslot='%d' AND isblock ='F'", lpDbOverlappedPlus->AccountInfo.szAccount, nSlot);

	if( !qry->Exec( szQuery1 ) )
	{
		WriteLog( "%s, %d\r\n\t%s", __FILE__, __LINE__, szQuery1 );
		FreeRequest( lpDbOverlappedPlus );
		return;
	}
	if( qry->Fetch() )
	{
		WriteLog( "[CHARACTER_CREATE]: %s tried to dupe .. ", lpDbOverlappedPlus->AccountInfo.szAccount );
		g_dpLoginSrvr.SendError( ERROR_USER_EXISTS, lpDbOverlappedPlus->dpid );
		FreeRequest( lpDbOverlappedPlus );
		return;
	}
	sprintf( szQuery1, "" );
	
	char szQuery[QUERY_SIZE]	= { 0,};
	DBQryCharacter( szQuery, "I1", 0, g_appInfo.dwSys, lpDbOverlappedPlus->AccountInfo.szAccount, lpDbOverlappedPlus->AccountInfo.szPlayer, nSlot, dwWorldID,
		dwIndex, vPos.x, vPos.y, vPos.z, '\0', nSkinSet, nHairMesh,	dwHairColor, nHeadMesh, nSex, 0.0f, 0, 0.0f, 0, 0, 0, 0, 0, nJob );

	if( FALSE == qry->Exec( szQuery ) )
	{
		WriteLog( "%s, %d\r\n\t%s", __FILE__, __LINE__, szQuery );
		FreeRequest( lpDbOverlappedPlus );
		return;
	}