2012-09-20 07:34 PM
The Flex language contains a find keyword which is very useful. Even though token and find are both string searches the way they are implemented differs and token is much faster than find. Due to the slower speed of find it is usually recommended that find is limited to searching no more than 512 bytes. So wouldn't it be great if there was a way to perform a find with the speed of a token match? Well there is and it uses and underused keyword called packet-payload. With find you locate the begining and end of the section of the session to search and call find. In this method we use token matches to locate of the begining, the end and the string. Then we do two comparisons to ensure that the token match for the search string was found within that section of the session. Below is a simplified version of my hidden Java applet parser (very simplified so don't try to use it) which walks you through the process of using payload-position in place of find.
<declaration>
<meta format="Text" key="risk.info" name="info"/>
<meta format="Text" key="applet" name="applet"/>
<string name="applet_content"/>
<string name="applet_string"/>
<number name="numtemp"/>
<number name="initial_position"/>
<number name="end_position"/>
<number name="current_position"/>
<number name="diff_position"/>
<!-- opening applet tag '<applet ' -->
<token name="applet_start" value="<applet "/>
<!-- closing applet tag '</applet' -->
<token name="applet_end" value="</applet"/>
<!-- If the width is set to 1 means the applet will not actually be visible which is suspicious. We want to make sure that we do not get 10 or 100, etc so we add the content most likely to come after the value, a space or '>' -->
<token name="width" value="width=1 "/>
<token name="width" value="width=1>"/>
</declaration>
<match name="applet_start">
<!-- This sets initial_position to the current read position which is immediately after '<applet ' -->
<payload-position name="initial_position"/>
</match>
<match name="applet_end">
<!-- This sets end_position to the current read position which is immediately after '</applet' -->
<payload-position name="end_position"/>
<!-- We actually want to be just before '</applet' but flex does not have a call for that. Instead we subtract the length of the token given us the correct number. -->
<decrement name="end_position" value="8"/>
</match>
<match name="width">
<!-- This sets current_position to the current read position which is immediately after 'width=1 ' -->
<payload-position name="current_position"/>
<!-- Now we have 3 locations within the packet, a start of the applet tag, the location of the width and the end of the applet tag. Using a find we would search for the width between the start and end positions. Instead we are just going to do two comparisons to see if the width is between the two numbers. Since flex doesn't support AND in an if statement we use nested ifs. -->
<if name="current_position" greater="$initial_position">
<if name="current_position" lessequal="$end_position">
<register name="info" value="java applet width 1"/>
<!-- If we want to read in the value of the applet string we already have all the information we need without using a find. Here we use a new variable and place our current read position into it.-->
<assign name="diff_position" value="$current_position"/>
<!-- Now we subtract the location of the '<applet' tag giving us the distance between the start position and our current location. -->
<decrement name="diff_position" value="$initial_position"/>
<!-- Moving backwards this amount places us at the read position of the '<applet ' match -->
<move direction="reverse" value="$diff_position">
<!-- Now we need to find the length between the start and the end. We will do this the same way. -->
<assign name="diff_position" value="$end_position"/>
<decrement name="diff_position" value="$initial_position"/>
<!-- All that is left is to read the length of the string we have now measured out. Remember to nest any actions that depend on the read inside of the read. This way if your read fails you don't try to use the NULL content of the applet_content variable. -->
<read length="diff_position" name="applet_content">
<!-- Lets put a string of 'applet content: ' ahead of the content so we know what we are looking at -->
<assign name="applet_string" value="applet content: "/>
<!-- Now we combine the actual content to our string and register it -->
<append name="applet_string" value="$applet_content"/>
<register name="applet" value="$applet_string"/>
</read>
</move>
</if>
</if>
</match>