Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: [AMF packet] Decoding AMF binary data

Hybrid View

  1. #1

    Joined
    Dec 2011
    Posts
    95
    Userbars
    4
    Thanks
    161
    Thanked
    172/63
    DL/UL
    32/3
    Mentioned
    87 times
    Time Online
    17d 12h 5m
    Avg. Time Online
    6m

    [AMF packet] Decoding AMF binary data

    I've done some research, trying to understand how to practically decode/decipher/deserialize an AMF binary data in a http content. So far, this is the result:

    This tutorial does not have the full list of value types and their standard encodings. For the full AMF specifications, search Adobe site for it.

    As most of hackers normally do it, editing and deciphering binary data is almost always done using a hex editor. So each byte in the AMF data used in this tutorial for explanation has its value represented in hexadecimal.

    OK, basically, AMF data in a http content contains encoded key-value pairs -- encoded by a Flash application or application running Actionscript, so that it can be sent to a Flash Media server or a client running Flash application.

    Key Value type value
    Name String John
    Age Number 30

    Now there are 2 versions of AMF to date: AMF0 and AMF3. In AMF0, value type can be indentified by looking at the value of its type-marker (a single byte). Following is a list of some of the value types with their type-marker values (They're in hexadecimal).

    Number - 00 (Encoded as IEEE 64-bit double precision floating point number)
    Boolean - 01 (Encoded as a single byte of value 00 or 01)
    String - 02 (ASCII encoded)
    Object - 03 (Set of key/value pairs)
    Null - 05
    Array - 08
    Object/Array End - 09

    So, a string, "John", encoded in AMF0 format will look something like this:
    02 00 04 4A 6F 68 6E

    The first byte (02) means that the data is string type (refer the list above). The next 2 bytes (00 04) is a number (16-bit unsigned integer) which tells the length (in byte) of the string. It has to be 4 because "John" is a 4 letter word. The next 4 bytes is of course the word "John" in ASCII encoding. This is only the encoding of a value of a key.

    Say we have a key-value pair that is like this: Name = John , where "John" is string type value.
    That key-value pair encoded in AMF0 format will look like this:
    00 04 4E 61 6D 65 02 00 04 4A 6F 68 6E

    The key name is "Name" and the value is "John". "Name" is a 4 letter word. Key name is always encoded as string. So the first 2 bytes (00 04) is straightaway the length of "Name". No need to specify a 02 before it because all decoder should always take key name as string. The next 4 bytes is of course "Name" in ASCII encoding. Next, we expect the value of "Name". The next byte is the type-marker of its value type. It is 02, so we know that the value type is string. The next 2 bytes (unsigned 16-bit integer) tells the length of the string in byte and it is obviously 4 letter so it has got to be 00 04. Finally, the last 4 bytes is "John" in ASCII encoding.

    For number type example, say we have a key-value pair that is like this: Age = 30 , where 30 is a number value.
    That key-value pair encoded in AMF0 format will look like this:
    00 03 41 67 65 00 40 3E 00 00 00 00 00 00

    "Age" is a 3 letter word so the first 2 bytes has to be 00 03. The next 3 bytes of course is "Age" in ASCII encoding. The remaining bytes is the data for its value. Since the value type is number, the type-marker is set to 00. Remember that all number type in AMF0 format are 8-bytes double precision floating point value. So there should be 8 bytes proceeding the type-marker. Age's value is 30, so 30 in double precision floating point value, represented in hexadecimal is 40 3E 00 00 00 00 00 00.

    We can also use the object type to send both of the key-value pairs above as an object type. An object type contains a series of key-value pairs. Picture of this in text representation (I'll do my best) is something like this:
    -(Object start) (Name = John), (Age = 30), (Object end)
    Now refering to the type-marker value list way above, object type marker value is 03 and object end marker value is 09 So the encoding for this object in AMF0 format will be like this:
    03 00 03 41 67 65 00 40 3E 00 00 00 00 00 00 00 04 4E 61 6D 65 02 00 04 4A 6F 68 6E 00 00 09

    If you look at the last 3 bytes, 09 is preceded by 2 bytes which is 00 00. This is because a decoder will take the 2 bytes as length of the next key name, and not a type marker. You need to specify 00 00 so that the decoder will take it that there is no key name and the next byte will be taken as a type-marker. Notice also that the key-value pairs are sorted in alphabetical order.

    Packet Structure of AMF in a http content
    An AMF data in a http content basically has this structure or shape (header section and body section):

    |--Header Section-----------------------------------------------
    -Header Name header value type is string
    -MustUnderstand a boolean value
    -your message or content
    |--Message Body------------------------------------------------
    -Target target value type is string
    -Response response value type is string
    -your message or content
    ---------------------------------------------------------------||

    For example AMF packet found in a http content, I take the http response of the spinning of the Neopets Wheel of Mediocrity flash game. The http response contains an AMF binary data and I saved it as a binary file and open it using a hex editor. The picture below shows the AMF binary data in hexadecimal.


    Each color of the boxes in the picture has its own meaning:
    Red box: version marker
    Yellow box: length of the proceeding data or data count.
    Black box: type-marker
    Purple box: key name
    Blue box: key value
    Side note: I don't really want to blur out the Neopets name cause I don't really care, but I hate making another account (heheh)

    Now, let's focus on the header section of the binary data.

    The first 2 bytes (in the red box) denotes the version of this AMF data. 00 00 means AMF0 version.
    The next 2 bytes (in the yellow box) specifies the number of header or how many header there is in this packet. You see, an AMF data can contain multiple messages in one packet. If it says 00 02 then you can be sure there is at least 2 messages packed in this one packet. But thankfully it's only one because it says 00 01
    As discussed before, the AMF packet structure is like this:

    |--Header Section-----------------------------------------------
    -Header Name header value type is string
    -MustUnderstand a boolean value
    -your message or content
    |--Message Body------------------------------------------------
    -Target target value type is string
    -Response response value type is string
    -your message or content
    ---------------------------------------------------------------||

    The next 2 bytes in the yellow box and followed by the bytes in the proceeding blue box is the value for Header Name (refer to the packet structure above). A decoder will take this first value as the value for Header Name. Since the value for it is already fixed as string, there is no need to specify the value type for it. Straightaway the length of the string value (00 12) and followed by the string itself ("AppendToGatewayUrl").
    The next single byte after the string value is the value for MustUnderstand. Since it is fixed as a boolean value, again, no need to specify a type-marker. A boolean value is always 1 byte (either 00 for False or 01 for True), no need to specify length. So, we can see that MustUnderstand value is False since it is 00.
    The next 4 bytes in the yellow box (00 00 00 2E) is a 32-bit unsigned integer that specifies the length (in bytes) of the proceeding content data (refer to the packet structure figure above)
    The next single byte (in the black box) after 00 00 00 2E is a type marker which has been set to 02. This means, that the value type for header content is string. Also means that the next 2 bytes would be a number that specifies the length of the proceeding string ("?PHPSESSID=7a69d45a40e354e68ffaaf1b13db72a7") .

    After that string value is a 2 byte in the yellow box (00 01). This 2 bytes tells how many Message body there is in this packet (thankfully it's 1 again).
    After this specification of how many Message body there is, a decoder would expect the next data to be the value for Target (again, refer to the packet structure figure above). Since the value for it is already fixed as string, there is no need to specify the value type (type-marker) for it. Straightaway the length of the string value (00 0B) and followed by the string itself ("/1/onResult").
    Next, a decoder would expect the value for Response. Since the value for it is already fixed as string, there is no need to specify the value type (type-marker) for it. Straightaway the length of the string value (00 04) and followed by the string itself ("null").
    The next 4 bytes, 00 00 01 67, is the length in byte of the remaining data for message body content.

    By now you should be able to decipher the remaining data.
    The decoding work can be represented as something like this:



    Some of the communication knowledge:
    The Response field is used by a client to specify Id of request, example "/1". Then the server would respond with "/1/onResult" if successful or "/1/onStatus" if fail, in the Target field.
    MustUnderstand if set to True means that the message receiver must understand the header part, if it does not understand, it will generate an error.
    AMF3 has different value of type-markers. So make sure to know whether an AMF data is encoded in AMF 0 or AMF 3. It is easy, if it does not make sense or weird, it has to be the other.


    Some incomplete research discussed
    The first two bytes in an AMF packet (in a http content) is supposed to be the version of AMF. But it does not seem to instruct a decoder (in a Flash application) to decode the AMF data according to the version specified here. The decoder always decode the value types as AMF0 no matter what version the first two bytes specifies. Maybe it only acts as version specifier, NOT an instruction to decode according to what version the 2 bytes says. Or maybe Actionscript or Flash does not make use of the first 2 bytes yet. Anyone who knows, clarification is much appreciated.

    Search via Google this file: amf0_spec_121207.pdf It is the full specification of AMF0.
    Last edited by damian002; 07-10-2012 at 04:48 AM. Reason: There was an obvious mistake in the hex editor box coloring. Corrected :)

  2. The Following 12 Users Say Thank You to damian002 For This Useful Post:

    DarkByte (07-09-2012),deathwish42 (07-09-2012),Demo (07-09-2012),Deny (06-28-2013),Ghosts (08-27-2014),j03 (07-09-2012),npm (10-12-2017),PiSquared (07-31-2013),Reemer (07-17-2012),Reese (07-09-2012),Tom (07-18-2012),Zachafer (07-09-2012)

  3. #2

    Joined
    Jan 2012
    Posts
    589
    Userbars
    3
    Thanks
    138
    Thanked
    885/217
    DL/UL
    6/0
    Mentioned
    386 times
    Time Online
    1d 18h 21m
    Avg. Time Online
    N/A
    +rep for the original content.

  4. #3

    Joined
    Jun 2012
    Posts
    1,699
    Thanks
    876
    Thanked
    2,881/1,142
    DL/UL
    44/1
    Mentioned
    562 times
    Time Online
    118d 6h 45m
    Avg. Time Online
    40m
    Great work this will save me alot of effort + rep!

  5. #4
    Saiyan Race
    j03's Avatar
    Joined
    Dec 2011
    Posts
    13,722
    Userbars
    166
    Thanks
    5,906
    Thanked
    33,078/6,609
    DL/UL
    23/36
    Mentioned
    3,867 times
    Time Online
    563d 5h 25m
    Avg. Time Online
    3h 13m
    Whoa I've been looking for something like this for such a long time now lol.

    Time to work on some new hacks. :3
    (you need an account to see links)
    (you need an account to see links)(you need an account to see links)

    ------------------------
    [02/24/2013] Stealth CORE is made into the first standalone Neopets auto-player.
    ------------------------


  6. The Following User Says Thank You to j03 For This Useful Post:

    runbikesurf (07-09-2012)

  7. #5

    Joined
    Dec 2011
    Posts
    95
    Userbars
    4
    Thanks
    161
    Thanked
    172/63
    DL/UL
    32/3
    Mentioned
    87 times
    Time Online
    17d 12h 5m
    Avg. Time Online
    6m
    Thanks all. and another fact: AMF can can be without a header by specifying header count as 00 00.
    K, enough with class, time for some games...

  8. #6

    Joined
    Jun 2012
    Posts
    1,699
    Thanks
    876
    Thanked
    2,881/1,142
    DL/UL
    44/1
    Mentioned
    562 times
    Time Online
    118d 6h 45m
    Avg. Time Online
    40m
    This is really helping me alot , keyquest uses this at least for its http request , there are still actual raw packets to simulate too . I have added a X-amf request to my httpwrapper and using this I am able to now create a keyquest room and sit inside it waiting for players to join without getting disconnected due to timeouts (I send back there ping/pong request).

    You will be credited for your work on this when I finish my project. I have also started to use on wheel of monotony ect.

  9. The Following User Says Thank You to DarkByte For This Useful Post:

    Ryan~ (07-17-2012)

  10. #7

    Joined
    Jun 2012
    Posts
    1,699
    Thanks
    876
    Thanked
    2,881/1,142
    DL/UL
    44/1
    Mentioned
    562 times
    Time Online
    118d 6h 45m
    Avg. Time Online
    40m
    ^^ I am using python for a bot atm:

    (you need an account to see links)

    Provides a amf wrapper ready to go .
    Last edited by DarkByte; 08-22-2012 at 07:33 PM. Reason: wrong link

  11. #8

    Joined
    Jul 2013
    Posts
    1
    Userbars
    0
    Thanks
    0
    Thanked
    0/0
    Mentioned
    Never
    Time Online
    25m
    Avg. Time Online
    N/A
    Is this still open? I'm looking to extract an AMF packet for a game that I have captured in Charles Proxy. I want to create a little Java program which can do the same call multiple times. I've done this for Android with JSON but I'm not at all familiar w/ AMF3. Can someone tell me how I can extract the information I've captured in Charlex Proxy and re-run it from a Java app? Thanks for the help

    ---------- Post added at 09:33 AM ---------- Previous post was at 09:19 AM ----------

    Is this still open? I'm looking to extract an AMF packet for a game that I have captured in Charles Proxy. I want to create a little Java program which can do the same call multiple times. I've done this for Android with JSON but I'm not at all familiar w/ AMF3. Can someone tell me how I can extract the information I've captured in Charlex Proxy and re-run it from a Java app? Thanks for the help

  12. #9
    Saiyan Race
    j03's Avatar
    Joined
    Dec 2011
    Posts
    13,722
    Userbars
    166
    Thanks
    5,906
    Thanked
    33,078/6,609
    DL/UL
    23/36
    Mentioned
    3,867 times
    Time Online
    563d 5h 25m
    Avg. Time Online
    3h 13m
    Quote Originally Posted by studlyswissdude2 View Post
    Is this still open? I'm looking to extract an AMF packet for a game that I have captured in Charles Proxy. I want to create a little Java program which can do the same call multiple times. I've done this for Android with JSON but I'm not at all familiar w/ AMF3. Can someone tell me how I can extract the information I've captured in Charlex Proxy and re-run it from a Java app? Thanks for the help

    ---------- Post added at 09:33 AM ---------- Previous post was at 09:19 AM ----------

    Is this still open? I'm looking to extract an AMF packet for a game that I have captured in Charles Proxy. I want to create a little Java program which can do the same call multiple times. I've done this for Android with JSON but I'm not at all familiar w/ AMF3. Can someone tell me how I can extract the information I've captured in Charlex Proxy and re-run it from a Java app? Thanks for the help
    Of course it is. The OP should be online around now, if not later today.

    @(you need an account to see links)
    Last edited by j03; 07-31-2013 at 11:18 AM.
    (you need an account to see links)
    (you need an account to see links)(you need an account to see links)

    ------------------------
    [02/24/2013] Stealth CORE is made into the first standalone Neopets auto-player.
    ------------------------


  13. The Following User Says Thank You to j03 For This Useful Post:

    damian002 (07-31-2013)

  14. #10

    Joined
    Dec 2011
    Posts
    95
    Userbars
    4
    Thanks
    161
    Thanked
    172/63
    DL/UL
    32/3
    Mentioned
    87 times
    Time Online
    17d 12h 5m
    Avg. Time Online
    6m
    Quote Originally Posted by studlyswissdude2 View Post
    Is this still open? I'm looking to extract an AMF packet for a game that I have captured in Charles Proxy. I want to create a little Java program which can do the same call multiple times. I've done this for Android with JSON but I'm not at all familiar w/ AMF3. Can someone tell me how I can extract the information I've captured in Charlex Proxy and re-run it from a Java app? Thanks for the help

    ---------- Post added at 09:33 AM ---------- Previous post was at 09:19 AM ----------

    Is this still open? I'm looking to extract an AMF packet for a game that I have captured in Charles Proxy. I want to create a little Java program which can do the same call multiple times. I've done this for Android with JSON but I'm not at all familiar w/ AMF3. Can someone tell me how I can extract the information I've captured in Charlex Proxy and re-run it from a Java app? Thanks for the help
    First, the AMF data that you want to extract must be from a HTTP message content. Since you are using Charles Proxy which I believe is a sniffer for HTTP traffic, I think the AMF packet you are trying to extract can be deciphered by following the guide/tutorial above.
    Secondly, the AMF data that you want to extract is in binary. So, if you copy and paste a binary data in this form:
    00 23 67 B5 C6
    you won't be copying it in binary. You would only be copying it in the text representation of the binary data.
    Bottomline is: find the command in your Charles Proxy to dump or save the binary data into a file to your computer.
    I have not used CHarles Proxy before, so you have to find or figure out yourself.
    Another problem with me is that I am not familiar with JAVA. I think you know how to send http message with JAVA because you said you've done it before. So, you must know how to send binary data with JAVA through HTTP, with Content-Type specified as AMF type in the http header. Because I am not familiar with JAVA, I don't know how. The binary data to be sent is in the file you save to your computer with the Charles Proxy. Ask a JAVA expert :p
    good luck in whatever you're trying to do.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •