Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't decrypt these strings

Preamble

I'm trying to disassemble and reverse-engineer a program whose author is long gone. The program provides some unique features that I have yet to find elsewhere and... I'm curious and intrigued by reverse-engineering the program. If you're just gonna try and help me find another program... don't bother.

The Problem

I'm using IDA Pro w/ Hex-Rays Decompiler to get some half-way decent pseudocode to try and speed up the reverse-engineering. One big thing that I think will help speed up things is to figure out what strings mean. So far, this is what I'm finding for strings that are more than 4 characters longer:

dword_131894E = 54264588;
dword_131894A = 51381002;
dword_1318946 = 51380998;
dword_1318942 = 52429571;
dword_131893E = 52298503;
runtimeVersion[0] = 836;
szIndex = 0;
do
{
  runtimeVersion[szIndex] = (runtimeVersion[szIndex] - 1) ^ (szIndex + 882) ^ 0x47;
  ++szIndex;
}
while ( szIndex < 11 );

From looking at similar pseudocode for strings that are three characters, and using the Hex-Rays hover overs for type information, here's how I'm understanding this:

  • runtimeVersion is a const wchar
  • this means it has Unicode characters (UTF-16)
  • the string is embedded in memory, but in this case, weakly encrypted (XOR?)

The above pseudocode is the same for all the big strings except the constant "882" is different for every string. I'm assuming this is some sort compile-time encryption or macro that finds strings one by one and "encrypts" them uniquely. The problem is, though, that I can't seem to get a proper looking string by replicating the pseudocode. Here's what I have in C#:

ushort[] newCharArray = new ushort[rawCharacters.Length];

// Go through and decode all of the characters.
ushort i = 0;
do {
    newCharArray[i] = (ushort)((i + 882) ^ (rawCharacters[i] - 1) ^ 0x47);
    ++i;
}
while (i < 11);

'rawCharacters' is a ushort array. I split each of those dword entries in half and treat each one as a ushort. I put them in the array starting from the bottom to the top... So the value assigned to runtimeVersion[0] gets added to my array first, then the value from dword_131893E, then dword_1318942, etc.

I'm not sure what I'm missing here. This seems like it's so simple that it should be cake to reverse and recover the strings, but I'm getting stumped on the conversion from the pseudocode to actual code.

Thoughts?

like image 455
Toby Lawrence Avatar asked Aug 11 '12 01:08

Toby Lawrence


1 Answers

Ok working through on a piece of paper here's what i get:

54264588 = 0x033c030c
51381002 = 0x0310030a
51380998 = 0x03100306
52429571 = 0x03200303
52298503 = 0x031E0307
836 = 0x0344
882 = 0x0372

v = 0x0076 = 0x47 ^ 0x0372 ^ (0x0344 - 1)
2 = 0x0032 = 0x47 ^ 0x0373 ^ (0x0307 - 1)
. = 0x002E = 0x47 ^ 0x0374 ^ (0x031E - 1)
0 = 0x0030 = 0x47 ^ 0x0375 ^ (0x0303 - 1)
. = 0x0076 = 0x47 ^ 0x0376 ^ (0x0320 - 1)
5 = 0x0035 = 0x47 ^ 0x0377 ^ (0x0306 - 1)
0 = 0x0030 = 0x47 ^ 0x0378 ^ (0x0310 - 1)
7 = 0x0037 = 0x47 ^ 0x0379 ^ (0x030a - 1)
2 = 0x0032 = 0x47 ^ 0x037a ^ (0x0310 - 1)
7 = 0x0037 = 0x47 ^ 0x037b ^ (0x030c - 1)
\0 = 0x0000 = 0x47 ^ 0x037c ^ (0x033c - 1)

Therefore the string is "v2.0.50727" I also checked the other endian option but this one looks much better. So i know this doesn't point out where your code is wrong but it should help you solve it with a debugger/printf.

Edit: added last 7 to string.

like image 66
Fenster34 Avatar answered Sep 29 '22 01:09

Fenster34