Thursday, December 9, 2010

Hex Encoded IP Permutation Challenge

Background
One well known technique to evade a web filtering proxy is to encode the host part of a URL in hex, binary, base32 etc.  I successfully tested this trick against a Privoxy proxy but it failed to work against Blue Coat proxy.  If the proxy server is clever enough to convert such simple obfuscations to a standard form prior to comparing the request against its policies, then this trick would not work.


Challenge
While experimenting with this proxy evasion trick, I ran across an algorithm challenge.  I am trying to write a script which would output all valid permutations of an IP comprised of hex and decimal values.  So, lets suppose we have an IP address (dotted decimal notation) 1.2.3.4 and it could also be represented in its hex notation as a.b.c.d (1.2.3.4 = a.b.c.d), such that a=1,b=2,c=3,d=4. I am trying to generate all valid permutation, for example a.2.3.4, 1.2.3.d, ab.3.4, a.2.cd etc.
A permutation is valid if it conforms to the following three simple rules:
  1. Permutation must have only 4 values, which could be either hex or decimal representation.  Example: ab.2.3.4 is invalid, because it has 5 values.  Two hex (a,b) and three decimal values (2,3,4).
  2. Only hex values can be combined together without a dot.  All other combinations must be separated by dot.  Example: ab.3.4 is valid, however a2.3.4 and a.23.4 are invalid.  The latter violates rule #1 as well.
  3. Position of the values are fixed.  So in our example, 'a' and 1 are the only two values which can hold the first octet (position), 'b' and 2 the second octet etc. etc.
If you have the programming chops to do this in an efficient manner, I would like to see the code or pseudo code.  You can either post your solution in the comments or email me.


Proposed (hack) Solution
Disclaimer: I am not a professional programmer, nor do I claim to be an accomplished programmer. 

#!/usr/bin/env python
import re
# Validate host permutation
permre = re.compile('0x0[a-f]{1}|0x[0-9]{2}|0x[0-9][a-f]|[0-9]{1,3}')
# To keep the focus on the algorithm, I am not including the code which
# populates the following lists based on a given dotted-decimal notation IP.
# I can include it in the comments if you really want to see it.
octet1 = ['101', '0x65', '0x650x14', '0x650x140x03', '0x650x140x030x04']
octet2 = ['20', '0x14', '0x140x03', '0x140x030x04']
octet3 = ['3', '0x03', '0x030x04']
octet4 = ['11', '0x0b']
# Holds all validated permutations
validPermutations = []
# Loop over each octet to get all permutations (i = index)
for i1 in range(len(octet1)):
    for i2 in range(len(octet2)):
        for i3 in range(len(octet3)):
            for i4 in range(len(octet4)):
                # first octet always present
                permutation = octet1[i1]
                # A valid permutation will never have more than 4 components
                # Skip octets 2,3 & 4 based on length
                if len( re.findall( permre, permutation ) ) == 1:
                        permutation = permutation + '.' + octet2[i2]
                if len( re.findall( permre, permutation ) ) == 2:
                        permutation = permutation + '.' + octet3[i3]
                if len( re.findall( permre, permutation ) ) == 3:
                        permutation = permutation + '.' + octet4[i4]
                # At this point we have constructed our permutation
                # Next, we validate the permutation using regex
                # if the permutation has 4 components and it is not
                # a duplicate, add to list
                if len( re.findall( permre,permutation ) ) == 4 and validPermutations.count( permutation ) == 0:
                        validPermutations.append( permutation )
for v in validPermutations:
    print v


Output
101.20.3.11
101.20.3.0x0b
101.20.0x03.11
101.20.0x03.0x0b
101.20.0x030x04
101.0x14.3.11
101.0x14.3.0x0b
101.0x14.0x03.11
101.0x14.0x03.0x0b
101.0x14.0x030x04
101.0x140x03.11
101.0x140x03.0x0b
101.0x140x030x04
0x65.20.3.11
0x65.20.3.0x0b
0x65.20.0x03.11
0x65.20.0x03.0x0b
0x65.20.0x030x04
0x65.0x14.3.11
0x65.0x14.3.0x0b
0x65.0x14.0x03.11
0x65.0x14.0x03.0x0b
0x65.0x14.0x030x04
0x65.0x140x03.11
0x65.0x140x03.0x0b
0x65.0x140x030x04
0x650x14.3.11
0x650x14.3.0x0b
0x650x14.0x03.11
0x650x14.0x03.0x0b
0x650x14.0x030x04
0x650x140x03.11
0x650x140x03.0x0b
0x650x140x030x04


I am told by a colleague of mine that in SQL world, this is knows as the "Cartesian product"If he gets around to solving this problem in SQL, I will post the solution with his permission.

Also, in the programming/math world this is known as a "Permutation" problem (although rule #3 makes it more complex).

Update (12-10-2010 10 AM)
It took George Shvartsberg mere hours to come up with the solution in MSQL. Now I know why he gets paid the big bucks :-)

George's Proposed Solution
select concatStr =  col1 + col2 + col3 + col4 + col5 + col6 + col7,
       col1, col2, col3, col4, col5, col6, col7
into #tmp
from (select col1 = '101' union select col1 = '0x65')v1, 
     (select col2 = '.' union select col2 = '')v2,
     (select col3 = '20' union select col3 = '0x14')v3,
     (select col4 = '.' union select col4 = '')v4,
     (select col5 = '3' union select col5 = '0x03')v5,
     (select col6 = '.' union select col6 = '')v6,
     (select col7 = '11' union select col7 = '0x0b')v7
order by 1
delete #tmp where col2 = '' and isnumeric(col1) + isnumeric(col3) != 0
delete #tmp where col4 = '' and isnumeric(col3) + isnumeric(col5) != 0
delete #tmp where col6 = '' and isnumeric(col5) + isnumeric(col7) != 0
select concatStr
from #tmp
order by 1

Output

concatStr
0x65.0x14.0x03.0x0b
0x65.0x14.0x03.11
0x65.0x14.0x030x0b
0x65.0x14.3.0x0b
0x65.0x14.3.11
0x65.0x140x03.0x0b
0x65.0x140x03.11
0x65.0x140x030x0b
0x65.20.0x03.0x0b
0x65.20.0x03.11
0x65.20.0x030x0b
0x65.20.3.0x0b
0x65.20.3.11
0x650x14.0x03.0x0b
0x650x14.0x03.11
0x650x14.0x030x0b
0x650x14.3.0x0b
0x650x14.3.11
0x650x140x03.0x0b
0x650x140x03.11
0x650x140x030x0b
101.0x14.0x03.0x0b
101.0x14.0x03.11
101.0x14.0x030x0b
101.0x14.3.0x0b
101.0x14.3.11
101.0x140x03.0x0b
101.0x140x03.11
101.0x140x030x0b
101.20.0x03.0x0b
101.20.0x03.11
101.20.0x030x0b
101.20.3.0x0b
101.20.3.11


Cheers,
VVK

No comments:

Post a Comment