• Unfortunately, we have experienced significant hard drive damage that requires urgent maintenance and rebuilding. The forum will be a state of read only until we install our new drives and rebuild all the configurations needed. Please follow our Facebook page for updates, we will be back up shortly! (The forum could go offline at any given time due to the nature of the failed drives whilst awaiting the upgrades.) When you see an Incapsula error, you know we are in the process of migration.

Find Packet structure IDA

Legendary Battlemage
Joined
Mar 7, 2013
Messages
686
Reaction score
43
Hello guys, y try update the givebuff structure in v148...

i have idb v148 sunnyboy:

i find in CWvsContext_OnPacket
opc givebuff 0x28
mixtamal6 - Find Packet structure IDA - RaGEZONE Forums


so. i jump to

Code:
result = [COLOR=#ff0000]sub_13BC2F0[/COLOR](a2, (int)lpMultiByteStr);

how to find structure givebuff ?

Code:
public static byte[] giveBuff(int buffid, int bufflength, Map<MapleBuffStat, Integer> statups, MapleStatEffect effect) {


the analyzing function is:



help
 
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
It's staring right at you? Maybe you should look at v95 or BMS v53 to understand how Buffs work.

- OnTemporaryStatSet -> This is your structure. You will have some bytes in the beginning in newer versions.
- SecondaryStat::EncodeForLocal -> This is your buff structure. This will tell you what buffstats follow what structure. Nexon will normally follow the same count of bytes, at least, they do this since beta all the way to v90. Idk about v148.
- OnTemporaryStatSet (End) -> At the end of this (after SecondaryStat) is a few bytes. These are for Delays and Movement Affecting Stats.

You are using OdinMS and will have to continue following their guidelines, but this will give you the structure. You can if-statement any "weird" buffs like DashSpeed and DashJump.

EDIT: Also, with IDA knowledge, you can find all buffstats and implement them in v148 using the v95 PDB. You can find newer ones as well, but you won't have Nexon names to identify them, thus causing you to have to guess or test them out to see what they do.
 
Upvote 0
Skilled Illusionist
Joined
Jul 17, 2010
Messages
333
Reaction score
165
Code:
v8 = sub_436FE0(&v135, a2, &v141);//SecondaryStat::DecodeForLocal
in SecondaryStat::DecodeForLocal, you'll see
Code:
CInPacket::DecodeBuffer(a3, &v3101, 52u);
This part is the buffmask, and next if-statement probably you'll assume it is for WATK(0x1, 1), but it isn't.
Code:
v4 = sub_409B40(&v2761, dword_19AFA88);
if ( sub_409BA0(v4) )
{
You need to know what dword_19AFA88 is.
1. Press X key (Jump to xref).
2. Go to the address at the bottom of showed list. (in this case, Address:sub_1609E80/Text:'mov ecx, offset dword_19AFA88')
Code:
___:01609E80                  sub     esp, 34h
___:01609E83                  push    1A0h
___:01609E88                  push    84h  //0x84=132
___:01609E8D                  push    1
___:01609E8F                  lea     ecx, [esp+40h+var_34]
___:01609E93                  call    sub_4095A0
___:01609E98                  mov     ecx, eax
___:01609E9A                  call    sub_4095D0
___:01609E9F                  push    eax
___:01609EA0                  mov     ecx, offset dword_19AFA88
___:01609EA5                  call    sub_409510
___:01609EAA                  add     esp, 34h
___:01609EAD                  retn
You don't have to create a function but if you did it you'll get a 'dynamic_initializer_for__CTS_???__' function.
Code:
v0 = sub_4095A0(1);
v1 = sub_4095D0(v0, 132);//shiftLeft
return sub_409510(dword_19AFA88, v1, 416u);
Now you can see that this is buffmask '1 << 132' (in odin style, probably, STR(0x10, 5))
 
Upvote 0
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
@Yuuroido

geebus, 52byte masks now? glad i'm still only v83~v90 area lol

also, idk if nexon has changed the count in v148 or not, but in v95 and below, the order is every 32flags a position changes. That would mean that in our uFlagTemp[] array, the correct mask is 1 << 4 & 0x7F, and is in position 4 (3 cuz arrays start at 0, 32*4 = 128 but 4-1 = 3).

however, since v95 and v148 is so big, nexon highly likely changed it completely. but if you look into shiftLeft it will show you how they "shiftLeft" their masks. In my version, highest position available is 3.
Code:
if ( v4 / 32 <= 3 )
  {
    v9 = bits & 0x1F;//0x1F == 31. values are from 0~31 for each position divided by 32.

Also, the reason why I do & 0x7F is just because thats the highest value nexon allows:
Code:
if ( (unsigned int)v4 > 0x7F )
  {
    UINT128::setValue(v3, 0);
    return v3;
  }
 
Upvote 0
Newbie Spellweaver
Joined
Aug 28, 2015
Messages
95
Reaction score
47
Code:
v8 = sub_436FE0(&v135, a2, &v141);//SecondaryStat::DecodeForLocal
in SecondaryStat::DecodeForLocal, you'll see
Code:
CInPacket::DecodeBuffer(a3, &v3101, 52u);
This part is the buffmask, and next if-statement probably you'll assume it is for WATK(0x1, 1), but it isn't.
Code:
v4 = sub_409B40(&v2761, dword_19AFA88);
if ( sub_409BA0(v4) )
{
You need to know what dword_19AFA88 is.
1. Press X key (Jump to xref).
2. Go to the address at the bottom of showed list. (in this case, Address:sub_1609E80/Text:'mov ecx, offset dword_19AFA88')
Code:
___:01609E80                  sub     esp, 34h
___:01609E83                  push    1A0h
___:01609E88                  push    84h  //0x84=132
___:01609E8D                  push    1
___:01609E8F                  lea     ecx, [esp+40h+var_34]
___:01609E93                  call    sub_4095A0
___:01609E98                  mov     ecx, eax
___:01609E9A                  call    sub_4095D0
___:01609E9F                  push    eax
___:01609EA0                  mov     ecx, offset dword_19AFA88
___:01609EA5                  call    sub_409510
___:01609EAA                  add     esp, 34h
___:01609EAD                  retn
You don't have to create a function but if you did it you'll get a 'dynamic_initializer_for__CTS_???__' function.
Code:
v0 = sub_4095A0(1);
v1 = sub_4095D0(v0, 132);//shiftLeft
return sub_409510(dword_19AFA88, v1, 416u);
Now you can see that this is buffmask '1 << 132' (in odin style, probably, STR(0x10, 5))

@Yuuroido

geebus, 52byte masks now? glad i'm still only v83~v90 area lol

also, idk if nexon has changed the count in v148 or not, but in v95 and below, the order is every 32flags a position changes. That would mean that in our uFlagTemp[] array, the correct mask is 1 << 4 & 0x7F, and is in position 4 (3 cuz arrays start at 0, 32*4 = 128 but 4-1 = 3).

however, since v95 and v148 is so big, nexon highly likely changed it completely. but if you look into shiftLeft it will show you how they "shiftLeft" their masks. In my version, highest position available is 3.
Code:
if ( v4 / 32 <= 3 )
  {
    v9 = bits & 0x1F;
Can someone of you guys explain me how to get the buffmast and the position ?
I didn't understand how he got from 132 the mask and the position :/
 
Upvote 0
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
Can someone of you guys explain me how to get the buffmast and the position ?
I didn't understand how he got from 132 the mask and the position :/

Because Nexon has all buffstats in the client. He xref'd himself to the function to find the position. Nexon labels all buffstats from 0~300 for example. This buffstat is in position 132 (132 in hexadecimal is 0x80, he just converted it to base 10). If you re-write your buffstats to match nexons, you'd follow the order I said (I find it very much more neat than OdinMS's).

Anyway, to my knowledge, doing the same thing nexon does but giving hexadecimal values is what Lithium does.

so, if you calculate it (and he did the same thing), shift 1 << 4; it is equivalent to 16. 16 in hexadecimal is 0x10. Knowing now I told you 132 / 32 gives you a position, I've noticed my positioning compared to Lithium is always + 1. 132/32 = 4. 4 + 1 = 5. Thus, the buffstat would result in being like he said, PAD(0x10, 5).
 
Upvote 0
Newbie Spellweaver
Joined
Aug 28, 2015
Messages
95
Reaction score
47
okay let me see if I understood for exmple I am using this one:
and the buffstat length is 64 so 174 / 64 = 2 + 1 = 3 so the position is 3 and the value is 1 << 3 (0x08) or 1 << 174 (0x4000)?
 
Upvote 0
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
okay let me see if I understood for exmple I am using this one:
and the buffstat length is 64 so 174 / 64 = 2 + 1 = 3 so the position is 3 and the value is 1 << 3 ?

Your sub is wrong, setBitNumber is for shiftLeft, and setBitNumber is inside of your shiftLeft's function.

As for your result, you're getting the hang of it, but just a little off. Yes, the position is 3 if your buffstat length is 64. However the value is 174 - (64 * 2), so 174 - 128 = 46, so value is 1 << 46. That would mean w/e that buffstat is (if your 64 length is correct), its BUFFSTAT(0x4000, 3)


EDIT: If it were 32 still, it'd be 1 << 18 pos 6 and in translation to lithium would be BUFFSTAT(0x40000, 7).
 
Upvote 0
Newbie Spellweaver
Joined
Aug 28, 2015
Messages
95
Reaction score
47
Your sub is wrong, setBitNumber is for shiftLeft, and setBitNumber is inside of your shiftLeft's function.

As for your result, you're getting the hang of it, but just a little off. Yes, the position is 3 if your buffstat length is 64. However the value is 174 - (64 * 2), so 174 - 128 = 46, so value is 1 << 46. That would mean w/e that buffstat is (if your 64 length is correct), its BUFFSTAT(0x4000, 3)
Okay thanks you very much I finally understood it :)
Btw if I am doing 1 << 174 its giving to me the same result for 1 << 46
 
Upvote 0
Skilled Illusionist
Joined
Jul 17, 2010
Messages
333
Reaction score
165
geebus, 52byte masks now? glad i'm still only v83~v90 area lol
Eric
According to v166 idb, it's 64 bytes now. lol

After You&I (Rising Heroes in GMS) patch(IIRC), they no longer use shiftLeft and use instead setBitNumber, so now we should use
Code:
value = 1 << (0x1F - (i & 0x1F));
position = 13 - (i >> 5);//52bytes->13ints, 64bytes->16ints
instead of
Code:
value = 1 << i;
position = i >> 5;
* i: shift count
 
Last edited:
Upvote 0
Skilled Illusionist
Joined
Jul 17, 2010
Messages
333
Reaction score
165
Yuuroido I meant the flags haha, instead of DecoderBuffer(x, 16) its DecodeBuffer(x, 52). But yeah, it's now 64bytes instead of 32.. geez, so many changes.
Oh.. my mistake (he was not talking about the flags), I meant the flags too. (v148:52bytes, v166:64bytes)
Too many buffs.. :*:
 
Upvote 0
Legendary Battlemage
Joined
Mar 7, 2013
Messages
686
Reaction score
43
thanks guys for replies!
@Eric you have the link file?

v95 or BMS v53
in the thread sunnyboy "Library of IDBs" not found v95 and BMS v53

download this v95 + leak



this file is the one you mentioned.

So I must first understand the buffstats to obtain the structure after givebuff ?
 
Upvote 0
Back
Top