Jump to content

[? Exploit] Crash GameServerThread - Pending more inspection.


Recommended Posts

A typical Sunday morning. (EDIT: Its Monday sorry , lost track of time.)

 

EDIT: Doesnt work exactly as i first speculated. Thanks nik.

 

 

Typical day today. I woke up in the morning, took my breakfast, then i thought, hmm lets go in msn see whats up with our server. Admin pms me, server crashed. Hmm , i try to login , loginserver works fine, but gameserver is displayed down. Ok probably some exception in gameserver, lets look at the log. Nothing ... Interesting situation ;) Going to loginserver, checking the log. NullPointerException. Hmm how did the loginserver npe ? Oops whats that , a strange packet. Ok lets look at the source. 5 mins later, source turns out to be exploitable.

 

Ok. Im fine with l2jserver having many unsanitized input with out checks for exceptions. But wait a minute. I run lameguard, that means no noob can run phx on my server. So apparently, the one that did this, was some guy who has already bypassed gameguard. Not some average person. And that exploit, its not around. Hmm, plot thickens ! Could it be some l2jserver developer ? Some arch enemy ? Dont know. What i know is that today you have an exploit that allows you to crash any login server of hi5 l2jserver. Maybe l2dc too since they copy l2jserver a lot. Since im pretty sure that the guy who uses the exploit, is an l2jserver developer and since im also sure that he is a big jackass, i thought hey ! Lets be a jackass too and release this to the public so everyone goes and wrecks havoc to servers. Now lets see how fast l2jserver devs will fix this :)

 

The exploit:

 

Lets look first at a packet that a user can craft and send to the server. Its called ReplyCharacters.java

 

public ReplyCharacters(byte[] decrypt, GameServerThread server)

{

super(decrypt);

String account = readS();

int chars = readC();

int charsToDel = readC();

long[] charsList = new long[charsToDel];

for (int i = 0; i < charsToDel; i++)

{

charsList = readQ();

}

LoginController.getInstance().setCharactersOnServer(account,

chars, charsList, server.getServerId());

}

 

Aside from all the other reads, we got a string read here from the client with the account name. Now that can be crafted to point to an account name that doesnt exist. Lets say we craft a packet and we send it to the server crafted with phx with altered account so as the account does not exist. Then look at the last call in the constructor. Lets see what this function does.

 

public void setCharactersOnServer(String account, int charsNum, long[] timeToDel, int serverId)

{

L2LoginClient client = _loginServerClients.get(account);

 

if (charsNum > 0)

client.setCharsOnServ(serverId, charsNum);

 

if (timeToDel.length > 0)

client.serCharsWaitingDelOnServ(serverId, timeToDel);

}

 

Wait a minute. There is no check if loginServerClients data structure contains an account with that name. So client may be null. But there is no null check afterwards. So a call to the client may crash the gameserver thread that handles the packet parsing and execution. Thread crashes, no more play!

 

 

The solution:

 

You can check for npe, but the best is not to handle many business logic in the gameserverthread. One reason why each packet gets scheduled in a different runnable is so as when an exception happens, the main thread serving the packets, not to crash. Thats why we dont do business logic in the constructor. We let the abstract RunImpl to be executed in a new runnable cause the constructor is called by the gameserverthread not the new task that executes the packet.

 

The greetings:

 

The one that did that to my server, well played. Oh and while you were taking your time to execute faulty packets, last night , i was focking your mother :)

 

Lets see how fast the l2jserver dev-spies will get to this :)

 

Edit: Hide hide hide!

Edit2 , reply to Edit1: Ya as if they dont have VIP spy accounts ;)

Link to comment
Share on other sites

If thats how you fix things, you sure have lots to learn yet. :)

 

 

Would be nice If you give the full script too

+1 anyway

 

I dont code hack scripts to execute exploits cause i find it totally stupid and unethical. Only l2jserver developers hide exploits and crash other servers ( cough Zekex cough ).

Link to comment
Share on other sites

Its easy, simple and fast fix. I dont know what do you expect more than this... a LS-GS/GS-LS communication rework?

 

Oh also there is a comment left in the no leechers zone of the l2jforums regarding you (i wont involve names here, i want to keep the poster anonymous, also i dont intend to offend you by this, its just an interesting comment that i want you to see):

Guy who wrote it is noob, its bug causing npe in part which shows player count on accs and thats not client communication, lol. login client was simply removed before packet with count arrived... and talking about lameguard in this situation  ::) n/c
Link to comment
Share on other sites

Read again the packet trace. The account name is sent by the client to the loginserver. The loginserver processes it and then it sends a ReplyCharacters to the gameserver. Tell that guy from your private zone to recheck what he says. I checked it 3 times to be sure cause i had my doubts too when i first saw the ls-gs communication. The requested account name is passed from client to loginserver and THEN to gameserverthread unfiltered. If thats not the case, then its probably some race that corrupts the data somehow. Ill recheck to be sure.

 

Even if its roots are not traced back to client, still an npe in the gameserverthread is not a small issue. And tell that guy from your private forum ( and i know who he is ! ), if im a noob, then what is he, that allows in his project, developers that call business logic inside the constructor ? Especially at his age. You see the tragic irony dont you ? ;)

 

login client was simply removed before packet with count arrived...

 

Thats even worse than exploiting a non-filtered input, dont you think ?

Link to comment
Share on other sites

When you successfully login at the server

java/com/l2jserver/loginserver/clientpackets/RequestAuthLogin.java

                                case AUTH_SUCCESS:

                                        client.setAccount(_user);

                                        lc.getCharactersOnAccount(_user);

                                        client.setState(LoginClientState.AUTHED_LOGIN);

                                        client.setSessionKey(lc.assignSessionKeyToClient(_user, client));

 

It requests char list on the successfully logged in account (it cant be nonexistant since it successfully logged in).

        public void getCharactersOnAccount(String account)

        {

                Collection<GameServerInfo> serverList = GameServerTable.getInstance().getRegisteredGameServers().values();

                for (GameServerInfo gsi : serverList)

                {

                        if (gsi.isAuthed())

                              gsi.getGameServerThread().requestCharacters(account);

                }

        }

        public void requestCharacters(String account)

        {

                RequestCharacters rc = new RequestCharacters(account);

                try

                {

                        sendPacket(rc);

                }

                catch (IOException e)

                {

                        e.printStackTrace();

                }

        }

The packet is sent to the GS

                                                case 0x05:

                                                        RequestCharacters rc = new RequestCharacters(decrypt);

                                                      getCharsOnServer(rc.getAccount());

                                                        break;

and LoginServerThread processes it

private void getCharsOnServer(String account)

{

Connection con = null;

int chars = 0;

List<Long> charToDel = new ArrayList<Long>();

try

{

con = L2DatabaseFactory.getInstance().getConnection();

PreparedStatement statement = con.prepareStatement("SELECT deletetime FROM characters WHERE account_name=?");

statement.setString(1, account);

ResultSet rset = statement.executeQuery();

while (rset.next())

{

chars++;

long delTime = rset.getLong("deletetime");

if (delTime != 0)

charToDel.add(delTime);

}

rset.close();

statement.close();

}

catch (SQLException e)

{

_log.log(Level.WARNING, "Exception: getCharsOnServer: " + e.getMessage(), e);

}

finally

{

L2DatabaseFactory.close(con);

}

 

ReplyCharacters rec = new ReplyCharacters(account, chars, charToDel);

try

{

sendPacket(rec);

}

catch (IOException e)

{

if (Config.DEBUG)

_log.log(Level.WARNING, "", e);

}

 

}

And eventually we reach ReplyCharacters...

 

 

Now... after tracing all this, tell me how can you call this algorithm using invalid account?

Link to comment
Share on other sites

Indeed i was wrong. I apologize for not being 6 years in l2j and cause i dont know all the 1700 files of code (that makes me a noob i guess ...) :) . Still doesnt explain why it causes an npe though. Cause might i have overlooked the previous one being careless, but my eyes dont fail me, the gameserverthread crashes. And i doubt im dellusional in that:

 

 

Exception in thread "GameServerThread-30@127.0.0.1" java.lang.NullPointerException

       at com.l2jserver.loginserver.LoginController.setCharactersOnServer(LoginController.java:509)

       at com.l2jserver.loginserver.network.gameserverpackets.ReplyCharacters.<init>(ReplyCharacters.java:41)

       at com.l2jserver.loginserver.network.L2JGameServerPacketHandler.handlePacket(L2JGameServerPacketHandler.java:87)

       at com.l2jserver.loginserver.GameServerThread.run(GameServerThread.java:133)

 

The gameserverthread doesnt wake up one morning and says "hey what a wonderful day, lets crash". Im waiting for some explanation from the "wise" l2jserver developers, who in their boundless wisdom call all us non l2jserver devs, noobs.

Link to comment
Share on other sites

Not knowing the l2j code doesnt make you a noob, nor knowing the whole code makes you pro. Its all about experience.

Also, l2j devs treat most ppl like that because they are just pissed off. Many idiots, leechers, noobs that think that they know a lot are behind all this.

Because 90% of the l2j community is like that, l2j devs are used to treat ppl like that, even ppl that do not deserve it.

 

Anyway, the reason that you got NPE is probably because somehow the account wasnt inside _loginServerClients

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



  • Posts

    • 2 Factor Authentication Code for 100% secure login. Account provided with full information (email, password, dob, gender, etc).
    • ready server for sale, also available for testing with ready and beautiful npc zone pvp with custom 2 epic core orfen lvl2 with all maps ready all quests work at 100% ready comm  board with buffer teleport gm shop service anyone interested send me a pm many more that I forget  Exp/Sp : x30 (Premium: x40)    Adena : x7 (Premium: x10)   Drop : x7 (Premium: 10)   Spoil : x7 (Premium: 10)   Seal Stones : x7 (Premium: 10)   Raid Boss EXP/SP : x10   Raid Boss Drop : x3 (Premium: x5)   Epic Boss Drop : x1 Enchants   Safe Enchant : +3   Max Enchant : +16   Normal Scroll of Enchant Chance : 55%   Blessed Scroll of Enchant Chance : 60% Game Features   GMShop (Max. B-Grade)   Mana Potions (1000 MP, 10 sec Cooldown)   NPC Buffer (Include all buffs, 2h duration)   Auto-learn skills (Except Divine Inspiration)   Global Gatekeeper   Skill Escape: 15 seconds or /unstuck   1st Class Transfer (Free)   2nd Class Transfer (Free)   3rd Class Transfer (700 halisha mark)   Subclass (Items required from Cabrio / Hallate / Kernon / Golkonda + Top B Weapon + 984 Cry B)   Subclass 5 Subclasses + Main (Previous subclasses to level 75 to add new one)   Noblesse (Full Retail Quest)   Buff Slots: 24 (28 with Divine Inspiration LVL 4)   Skill Sweeper Festival added (Scavenger level 36)   Skill Block Buff added   Maximum delevel to keep Skills: 10 Levels   Shift + Click to see Droplist   Global Shout & Trade Chat   Retail Geodata and Pathnodes   Seven Signs Retail   Merchant and Blacksmith of Mammon at towns   Dimensional Rift (Min. 3 people in party to enter - Instance)   Tyrannosaurus drop Top LS with fixed 50% chance   Fast Augmentation System (Using Life Stones from Inventory)   Chance of getting skills (Normal 1%, Mid 3%, High 5%, Top 10%)   Wedding System with 30 seconds teleport to husband/wife Olympiad & Siege   Olympiad circle 14 days. (Maximum Enchant +6)   Olympiads time 18:00 - 00:00 (GMT +3)   Non-class 5 minimum participants to begin   Class based disabled   Siege every week.   To gain the reward you need to keep the Castle 2 times. Clans, Alliances & Limits   Max Clients/PC: 2   Max Clan Members: 36   Alliances allowed (Max 1 Clans)   24H Clan Penalties   Alliance penalty reset at daily restart (3-5 AM)   To bid for a Clan Hall required Clan Level 6 Quests x3   Alliance with the Ketra Orcs   Alliance with the Varka Silenos   War with Ketra Orcs   War with the Varka Silenos   The Finest Food   A Powerful Primeval Creature   Legacy of Insolence   Exploration of Giants Cave Part 1   Exploration of Giants Cave Part 2   Seekers of the Holy Grail   Guardians of the Holy Grail   Hunt of the Golden Ram Mercenary Force   The Zero Hour   Delicious Top Choice Meat   Heart in Search of Power   Rise and Fall of the Elroki Tribe   Yoke of the Past     Renegade Boss (Monday to Friday 20:00)   All Raid Boss 18+1 hours random respawn   Core (Jewel +1 STR +1 DEX) Monday, Wednesday and Friday 20:00 - 21:00 (Maximum level allowed to enter Cruma Tower: 80)   Orfen (Jewel +1 INT +1 WIT) Monday to Friday, 20:00 - 21:00 (Maximum level allowed to enter Sea of Spores: 80)   Ant Queen Monday and Friday 21:00 - 22:00 (Maximum level allowed to enter Ant Nest: 80)   Zaken Monday,Wednesday,Friday 22:00 - 23:00 (Maximum level allowed to enter Devil's Isle: 80)   Frintezza Tuesday, Thursday and Sunday 22:00 – 23:00 (Need CC of 4 party and 7 people in each party min to join the lair, max is 8 party of 9 people each)   Baium (lvl80) Saturday 22:00 – 23:00   Antharas Every 2 Saturdays 22:00 - 23:00 Every 2 Sundays (alternating with Valakas) 22:00 – 23:00   Valakas Every 2 Saturdays 22:00 - 23:00 Every 2 Sundays (alternating with Antharas) 22:00 – 23:00   Subclass Raids (Cabrio, Kernon, Hallate, Golkonda) 18hours + 1 random   Noblesse Raid (Barakiel) 6 hours + 15min random   Varka’s Hero Shadith 8 hours + 30 mins random (4th lvl of alliance with Ketra)   Ketra’s Hero Hekaton 8 hours + 30 mins random (4th lvl of alliance with Varka)   Varka’s Commander Mos 8 hours + 30 mins random (5th lvl of alliance with Ketra)   Ketra’s Commander Tayr 8 hours + 30 mins random (5th lvl of alliance with Varka)
    • Have a great day! Unfortunately, we can not give you the codes at the moment, but they will be distributed as soon as trial is back online, thanks for understanding! Other users also can reply there for codes, we will send them out some time after.
    • Ok mates i would like to play a pridestyle server (interluide, gracie w/ever) Is there any such server online and worth playing?
  • Topics

×
×
  • Create New...

AdBlock Extension Detected!

Our website is made possible by displaying online advertisements to our members.

Please disable AdBlock browser extension first, to be able to use our community.

I've Disabled AdBlock