Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

DZone's Guide to

# Alphanumeric Shifting Made Easy With Python

### Thanks to a couple of built-in functions, this dev was able to use Python to easily solve an otherwise rather complex puzzle. Read on to see how!

· Web Dev Zone ·
Free Resource

Comment (0)

Save
{{ articles[0].views | formatCount}} Views

Bugsnag monitors application stability, so you can make data-driven decisions on whether you should be building new features, or fixing bugs. Learn more.

During my first CTF(Capture the Flag) competition I noticed that some challenges required a character shifting in order to discover the real value of a string. I spent a few minutes on those challenges trying to figure out a pattern that could be applied to “unmask” the given content.

### Challenge 1

After gathering information about the given IP address, a file was found with the following content:

``rxms{DqhqdeqpRxms}``

It looks completely random, but given the fact that the flags had a pattern of: “flag{some-hash-here}”, we could try a character shifting:

``````rxms{DqhqdeqpRxms}
synt
tzou
uapv
vbqw
wcrx
xdsy
yetz
zfua
agvb
bhwc
cixd
djye
ekzf
flag{...} <- real content``````

We had to jump 12 positions in the alphabet to get the real content of the string.

### Challenge 2

In order to connect to a service we had to solve a pass-phrase code:

``AQW UJCNN PQV RCUU``

At first glance, the pass-phrase code looks like a Caesar’s Cipher. Solving this challenge also required character shifting, but this time, backward:

``````AQW UJCNN PQV RCUU
ZPV TIBMM OPU QBTT
YOU SHALL NOT PASS <- backward content``````

### Python to the Rescue

Python has the built-in functions ord() and chr() that can help us to accomplish this task:

``````class Alphanumeric(object):

ALPHABET_LENGTH = 26

def __init__(self, nrange=None):
self.current_letter = 'z'
self.current_number = 0
self.nrange = nrange

def forward_letter(self, letter, positions):
if letter.islower():
unicode_point = ord('a')
else:
unicode_point = ord('A')

start = ord(letter) - unicode_point
offset = ((start + positions) % self.ALPHABET_LENGTH) + unicode_point
self.current_letter = chr(offset)
return self.current_letter

def backward_letter(self, letter, positions):
if letter.islower():
unicode_point = ord('a')
else:
unicode_point = ord('A')

start = ord(letter) - unicode_point
offset = ((start - positions) % self.ALPHABET_LENGTH) + unicode_point
self.current_letter = chr(offset)
return self.current_letter

def next_letter(self):
return self.forward_letter(self.current_letter, 1)

def previous_letter(self):
return self.backward_letter(self.current_letter, 1)

def forward_number(self, number, positions):
if not self.nrange:
self.current_number = number + positions
return self.current_number

index = self.nrange.index(number)
start = index + positions
offset = (start % len(self.nrange))
self.current_number = self.nrange[offset]
return self.current_number

def backward_number(self, number, positions):
if not self.nrange:
return number - positions

index = self.nrange.index(number)
start = index - positions
offset = (start % len(self.nrange))
self.current_number = self.nrange[offset]
return self.current_number

def next_number(self):
return self.forward_number(self.current_number, 1)

def previous_number(self):
return self.backward_number(self.current_number, 1)

def forward_alphanumeric(self, alpha, positions, ignore_numbers=False, ignore_letters=False):
result = ""
for char in alpha:
if char.isdigit() and not ignore_numbers:
char = str(self.forward_number(int(char), positions))

if char.isalpha() and not ignore_letters:
char = self.forward_letter(char, positions)

result += char

return result

def backward_alphanumeric(self, alpha, positions, ignore_numbers=False, ignore_letters=False):
result = ""
for char in alpha:
if char.isdigit() and not ignore_numbers:
char = str(self.backward_number(int(char), positions))

if char.isalpha() and not ignore_letters:
char = self.backward_letter(char, positions)

result += char

return result``````

Using the Alphanumeric class:

``````alpha = Alphanumeric()
print alpha.forward_alphanumeric('abc123', 1)
print alpha.backward_alphanumeric('abc123', 1)

// prints: bcd234
// prints: zab012``````

Note that you can define a range of numbers to perform a “cyclic loop” when shifting numbers:

``````alpha = Alphanumeric([1, 2, 3, 4 , 5])
print alpha.forward_alphanumeric('123', 6)

// prints: 234``````

### A CLI Tool to the Rescue

Thinking about the next CTF’s challenges I wrote a small CLI tool called shift that makes it easier to shift alphanumeric characters.

``````echo "Dqhqdeqp Oazfqzf" | python shift.py -p 12 --backwards
// prints: "Reversed Content"

python shift.py abc123 -p 5
// prints: "fgh678"``````

You can see the documentation and the source code as well on GitHub.

Monitor application stability with Bugsnag to decide if your engineering team should be building new features on your roadmap or fixing bugs to stabilize your application.Try it free.

Topics:
python ,web dev ,python functions

Comment (0)

Save
{{ articles[0].views | formatCount}} Views

Opinions expressed by DZone contributors are their own.