Jump to content

Fix hairstyle can't over 29 for 2017+ client


jchcc

Recommended Posts


  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  37
  • Reputation:   19
  • Joined:  03/28/17
  • Last Seen:  

Hi, everyone.

The reason 2017 client crash while hairstyle over 29 is the client fetching palette's file name from hard-code table instead of hairstyle IDs.

 

Solution:

replace Enable64kHairstyle.qs

 

 

It work well with my 2017-06-14bRagexeRE & 2017-05-17aRagexeRE clients, and it should be fine with 2018's client.

Edited by jchcc
  • Upvote 2
Link to comment
Share on other sites


  • Group:  Developer
  • Topic Count:  50
  • Topics Per Day:  0.02
  • Content Count:  763
  • Reputation:   227
  • Joined:  02/11/17
  • Last Seen:  

Well it old clients is different from new client so don't expect it to work in newer clients unless there is an update in nemo. :))

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  53
  • Topics Per Day:  0.01
  • Content Count:  411
  • Reputation:   261
  • Joined:  04/25/12
  • Last Seen:  

Thanks a lot

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  2
  • Topics Per Day:  0.00
  • Content Count:  5
  • Reputation:   1
  • Joined:  04/24/18
  • Last Seen:  

 

15 hours ago, jchcc said:

Hi, everyone.

The reason 2017 client crash while hairstyle over 29 is the client fetching palette's file name from hard-code table instead of hairstyle IDs.

 

Solution:

edit Enable64kHairstyle.qs

here is the code:


    //Step p_1a - Find address of Format String
    code = "\xB8\xD3\xB8\xAE\\\xB8\xD3\xB8\xAE%s_%s_%d.pal"; // "머리\머리%s_%s_%d.pal"
    offset = exe.findString(code, RAW);

    
    if (offset === -1)
        return "Failed in Step p_1 - String not found";

    //Step p_1b - Change the 1st %s to %u
    exe.replace(offset + code.length - 0xB, "75", PTYPE_HEX);

    //Step p_1c - Find the string reference
    offset = exe.findCode("68" + exe.Raw2Rva(offset).packToHex(4), PTYPE_HEX, false);
    if (offset === -1)
        return "Failed in Step p_1 - String reference missing";

    //Step p_2a - Move offset to previous instruction which should be an LEA reg, [ESP+x] or LEA reg, [EBP-x]
    fpEnb = HasFramePointer();
    if (!fpEnb)
        offset = offset - 4;
    else
        offset = offset - 3;

    if (exe.fetchUByte(offset) !== 0x8D) // x > 0x7F => accomodating for the extra 3 bytes of x
        offset = offset - 3;

    if (exe.fetchUByte(offset) !== 0x8D)
        return "Failed in Step p_2 - Unknown instruction before reference";

    //Step p_2b - Extract the register code used in the first last PUSH reg32 before the LEA instruction (0x8D)
    regNum = exe.fetchUByte(offset - 1) - 0x50;
    if (regNum < 0 || regNum > 7)
        return "Failed in Step 2 - Missing Reg PUSH";

    if (fpEnb)
        regc = (0x45 | (regNum << 3)).packToHex(1);
    else
        regc = (0x44 | (regNum << 3)).packToHex(1);

    //Step 2c - Now look for the location where it is assigned. Dont remove the AB at the end, the code size is used later.
    if (fpEnb)
	{
		code =
		  " 8D" + regc + " AB"    //LEA reg32, [EBP-z] ; z = y+5*4
		+ " 0F 43" + regc + " AB" //CMOVAE reg32, DWORD PTR SS:[EBP-z]
		;
	}
	else
	{
		code =
		  " 8D" + regc + " 24 AB"    //LEA reg32, [ESP+z] ; z = y+5*4
		+ " 0F 43" + regc + " 24 AB" //CMOVAE reg32, DWORD PTR SS:[ESP+z]
		;
	}

	offset2 = exe.find(code, PTYPE_HEX, true, "\xAB", offset - 0x50, offset);

    if (offset2 === -1)
        return "Failed in Step p_2 - Register assignment missing";

    //Step p_2d - Save the offset2 and code size (We need to NOP out the excess)
    assignOffset = offset2;
    csize = code.hexlength();

    //Step p_3a - Find the start of the function (has a common signature like many others)
    code =
        " 6A FF"             //PUSH -1
      + " 68 AB AB AB 00"    //PUSH value
      + " 64 A1 00 00 00 00" //MOV EAX, FS:[0]
      + " 50"                //PUSH EAX
      + " 83 EC"             //SUB ESP, const
      ;
    offset = exe.find(code, PTYPE_HEX, true, "\xAB", offset2 - 0x1B0, offset2);

    if (offset === -1)
    {  //const is > 0x7F
        code =
          " 6A FF"             //PUSH -1
        + " 68 AB AB AB 00"    //PUSH value
        + " 64 A1 00 00 00 00" //MOV EAX, FS:[0]
        + " 50"                //PUSH EAX
        + " 81 EC"             //SUB ESP, const
        ;
        offset = exe.find(code, PTYPE_HEX, true, "\xAB", offset2 - 0x280, offset2);
    }

    if (offset === -1)
    { // 2017 +
        offset = exe.find(code, PTYPE_HEX, true, "\xAB", offset2 - 0x3A5, offset2);
    }

    if (offset === -1)
        return "Failed in Step p_3 - Function start missing";

    offset += code.hexlength();

    //Step p_3b - Get the Stack offset w.r.t. ESP/EBP for Arg.2
    var arg2Dist = 2*4; //for the 5 PUSHes of the arguments

    if (fpEnb)
    {
        arg2Dist += 4; //Account for the PUSH EBP in the beginning
    }
    else
    {
        arg2Dist += 4*4;//Account for PUSH -1, PUSH addr and 5 reg32 PUSHes

        if (exe.fetchUByte(offset - 2) === 0x81) // Add the const from SUB ESP, const
            arg2Dist += exe.fetchDWord(offset);
        else
            arg2Dist += exe.fetchByte(offset);

        //Step p_3c - Account for an extra PUSH instruction (security related) in VC9 clients
        code =
            " A1 AB AB AB 00" //MOV EAX, DWORD PTR DS:[__security_cookie];
          + " 33 C4"          //XOR EAX, ESP
          + " 50"             //PUSH EAX
          ;
        if (exe.find(code, PTYPE_HEX, true, "\xAB", offset + 0x4, offset + 0x20) !== -1)
            arg2Dist += 4;
    }
    //Step p_3d - Prep code to change assignment (hairstyle index instead of the string)
    if (fpEnb)
    {
        code = " 8B" + regc + arg2Dist.packToHex(1); //MOV reg32_A, DWORD PTR SS:[EBP + arg2Dist]; ARG.2
    }
    else if (arg2Dist > 0x7F)
    {
        code = " 8B" + (0x84 | (regNum << 3)).packToHex(1) + " 24" + arg2Dist.packToHex(4); //MOV reg32_A, DWORD PTR SS:[ESP + arg2Dist]; ARG.2
    }
    else
    {
        code = " 8B" + regc + " 24" + arg2Dist.packToHex(1); //MOV reg32_A, DWORD PTR SS:[ESP + arg2Dist]; ARG.2
    }

    code += " 90".repeat(csize - code.hexlength());//Fill rest with NOPs

    //Step p_3e - Replace the original at assignOffset
    exe.replace(assignOffset, code, PTYPE_HEX);

    //Step p_4a - Find the string table fetchers
 	code =
	    " 8B AB AB AB AB 00" //MOV reg32_A, DWORD PTR DS:[addr]
	  + " 8B 14"             //MOV EDX, DWORD PTR DS:[reg32_B * 4 + reg32_A]
	  ;
	offsets = exe.findAll(code, PTYPE_HEX, true, "\xAB", offset, assignOffset);
    
    if (offsets.length === 0)
    {
        code =
            " A1 AB AB AB 00"    //MOV reg32_A, DWORD PTR DS:[addr]
          + " 8B 14"             //MOV EDX, DWORD PTR DS:[reg32_B * 4 + reg32_A]
          ;
        offsets = exe.findAll(code, PTYPE_HEX, true, "\xAB", offset, assignOffset);
    }

    if (offsets.length === 0)
    {  // 2017 +
        code =
            " A1 AB AB AB 01"    //MOV reg32_A, DWORD PTR DS:[addr]
          + " 8B 14"             //MOV EDX, DWORD PTR DS:[reg32_B * 4 + reg32_A
          ;
        offsets = exe.findAll(code, PTYPE_HEX, true, "\xAB", offset, assignOffset);
    }

    if (offsets.length === 0)
        return "Failed in Step p_4 - Table fetchers missing";

    //Step p_4b - Remove the reg32_B * 4 from all the matches
    for (var i = 0; i < offsets.length; i++)
    {
        offset2 = offsets[i] + code.hexlength();
        exe.replaceWord(offset2 - 1, 0x9010 + (exe.fetchByte(offset2) & 0x7));
    }

paste before:


    return true;
}

 

It work well with my 2017-06-14bRagexeRE & 2017-05-17aRagexeRE clients, and it should be fine with 2018's client.

Hello here not work https://pastebin.com/nJakdpBG

My hexed is 2017-05-17

Edited by Horvath
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  37
  • Reputation:   19
  • Joined:  03/28/17
  • Last Seen:  

4 hours ago, Horvath said:

 

Hello here not work https://pastebin.com/nJakdpBG

My hexed is 2017-05-17

Still get crash? or diff error?

Please provide error message or pic.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  2
  • Topics Per Day:  0.00
  • Content Count:  5
  • Reputation:   1
  • Joined:  04/24/18
  • Last Seen:  

8 hours ago, jchcc said:

Still get crash? or diff error?

Please provide error message or pic.

It stops running at the same time, does not show sprite error, simply stops shortly after it exceeds 29

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  37
  • Reputation:   19
  • Joined:  03/28/17
  • Last Seen:  

14 minutes ago, Horvath said:

It stops running at the same time, does not show sprite error, simply stops shortly after it exceeds 29

or please send me the file.

The first client I testing is 2017-05-17, and it work.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  2
  • Topics Per Day:  0.00
  • Content Count:  5
  • Reputation:   1
  • Joined:  04/24/18
  • Last Seen:  

8 minutes ago, jchcc said:

or please send me the file.

The first client I testing is 2017-05-17, and it work.

here its https://pastebin.com/nJakdpBG

Enable64kHairstyle.qs

  • Like 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  37
  • Reputation:   19
  • Joined:  03/28/17
  • Last Seen:  

There is no issue on the files.

1533821232813.jpg.b7c72eba2a54d3e9382b1a12a80825a2.jpg

1533821110538.jpg.64bce35650e9466064acc0f1f1ce5f53.jpg

 

So,

check your grf has hairstyle & palette files,

diff with a clean client.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  2
  • Topics Per Day:  0.00
  • Content Count:  6
  • Reputation:   0
  • Joined:  04/11/18
  • Last Seen:  

hello, can someone please provide me the .grf with the 64k hairstyle, I only have 28 in my data.grf

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.

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.

×
×
  • Create New...