You can find the full source code of the project in this Github project
Introduction
From Wikipedia ([1]) we can read that a Mealy machine is a finite-state machine whose output values are determined both by its current state and the current inputs. There are plenty of information on the internet about this concept, so I will not go into further details. What is interesting to us is that by having an automata, we can give it a specific input and have the computed string as output.The idea of using a Mealy machine to obfuscate strings is not new and it was already presented in [2]. Unfortunately the book doesn't explains how to create a Mealy automata in an automatic way. As the task of creating an automata manually, for each of the strings, is very time consuming, I felt that a very important part was missing.
In the following paragraphs I'll try to fill this hole by providing you with a possible implementation.
In the final section we will see an example that uses the code presented in the book.
Why using a new method?
If you have ever reversed a binary which use obfuscation you might have noticed that most of the obfuscation strategies are based on using some kind of know cryptographic algorithm or by using a custom encoder based on ADD/XOR/ROL instructions. Both cases have advantages and disadvantage (using a XOR obfuscation is a weak method, see [3]), but both are based on the assumption that they have the data encoded/encrypted in some way in the binary. In our case we convert the data in "code" that generates the decoded value at runtime.For our purpose we will use a Mealy machine which has 0/1 as input. This choice will allow us to encode each letter with a bit, greatly reducing the input representation.
Implementation
Let's consider a simple automata (created with [4]):On each arrow there is the input and the associated output. If we consider the state 0 as the initial one and pass the input string: 0 1 1 0 1 0 0 we will receive as output the string ANTONIA.
In order to automatically generates the automata I found that starting by considering the input was a pretty challenging task. So I changed strategy and considered the output in order to create the automata. For each character, the choice is between creating a new state, or connecting to one of the already existing states. You can find the full F# source code implementation with a test example here.
Testing
Now that we have an algorithm to generate the automata, let's try to obfuscate some strings. Since the implementation was done in F# I'll create an helper method to print the automata in an handy way in order to import the result in a C program. Let's consider the string supersecretpassword. The automata and the input generated from this string are (the result may be different on your machine):Input text: supersecretpassword Input: 1,1,0,0,0,1,0,0,0,0,1,0,1,0,1,1,1,1,0, Int: 250915 Output: {{'e', 's'}, {'e', 'u'}, {'p', 'e'}, {'e', 'a'}, {'r', 'r'}, {'c', 'w'}, {'d', 't'}, {'s', 'd'}, {'u', 's'}, {'p', 'w'}, {'a', 'o'}, {'d', 's'}, {'s', 'p'}} Automata: {{6, 1}, {5, 2}, {3, 2}, {4, 7}, {0, 11}, {4, 12}, {12, 2}, {8, 4}, {12, 9}, {0, 10}, {6, 4}, {12, 7}, {11, 10}}
Since the length of the string is less than 32 characters, we can convert the binary input into a DWORD. Now let's write a C program that reconstruct the given string:
#include "stdafx.h" void deobfuscate(char* text, int length, int key, char automata[][2], char output[][2]) { int v = 0, state = 0, i = 0; for (i = 0; i < length; i++) { v = key & 1; key >>= 1; text[i] = output[state][v]; state = automata[state][v]; } text[i] = '\0'; } int main() { char text[20]; int key = 250915; char automata[][2] = { { 6, 1 },{ 5, 2 },{ 3, 2 },{ 4, 7 },{ 0, 11 }, { 4, 12 },{ 12, 2 },{ 8, 4 },{ 12, 9 },{ 0, 10 }, { 6, 4 },{ 12, 7 },{ 11, 10 } }; char output[][2] = { { 'e', 's' },{ 'e', 'u' },{ 'p', 'e' },{ 'e', 'a' }, { 'r', 'r' },{ 'c', 'w' },{ 'd', 't' },{ 's', 'd' }, { 'u', 's' },{ 'p', 'w' },{ 'a', 'o' },{ 'd', 's' }, { 's', 'p' } }; deobfuscate(text, sizeof(text)-1, key, automata, output); printf("Output: %s", text); return 0; }
If we run this code we can see that the string "supersecretpassword" will be displayed in the console :)
Conclusion
I hope that you enjoyed this post as much as I enjoyed to write the code. If you find any errors or you know a better algorithm to implement the Mealy automata just leave a comment or drop me an email ;)References
[1] Mealy machine[2] Surreptitious Software: Obfuscation, Watermarking, and Tamperproofing for Software Protection
[3] XORSearch & XORStrings
[4] Finite State Machine Designer