Log in

View Full Version : Reversing a home cooked encryption routine


markh51
November 15th, 2005, 07:35
I am working on reversing a home cooked encrytion routine which takes a 8 byte device ID to generate a 8 byte password. I am trying to create a utility so I can enter the device ID to generate the password.

This is what I have so far:
ID: B8 54 24 02 17 00 00 00

The first part of the routine takes the ID and XOR's each byte like:
XOR B8, 3A = 82
XOR 54, E5 = B1
XOR 24, 3A = 1E
XOR 02, E5 = E7
XOR 17, 3A = 2D
XOR 00, E5 = E5
XOR 00, 3A = 3A
XOR 00, E5 = E5

So the encrypted ID is: 82 B1 1E E7 2D E5 3A E5

The first 4 bytes (82 B1 1E E7) is MOV'd into EAX then PUSH'd then a call to 0045D160 (posted below) is made. When this sub returns, EAX contains the first 4 bytes of the password. The sub is then called again, this time with the second part of the ID to generate the last part of the password.

The generated password is: BB 9F 65 97 8F EB 0D 45

Code:
.text:0045D160 var_4 = dword ptr -4
.text:0045D160 arg_0 = dword ptr 8
.text:0045D160 arg_4 = dword ptr 0Ch
.text:0045D160 arg_8 = dword ptr 10h
.text:0045D160
.text:0045D160 push ebp
.text:0045D161 mov ebp, esp
.text:0045D163 sub esp, 4
.text:0045D166 push ebx
.text:0045D167 push esi
.text:0045D168 push edi
.text:0045D169
.text:0045D169 loc_45D169: ; CODE XREF: sub_45D160+46j
.text:0045D169 mov eax, [ebp+arg_8]
.text:0045D16C mov [ebp+var_4], eax
.text:0045D16F dec [ebp+arg_8]
.text:0045D172 cmp [ebp+var_4], 0
.text:0045D176 jz loc_45D1AB
.text:0045D17C mov eax, [ebp+arg_4]
.text:0045D17F xor ecx, ecx
.text:0045D181 mov cl, [eax]
.text:0045D183 mov eax, [ebp+arg_0]
.text:0045D186 shr eax, 18h
.text:0045D189 xor ecx, eax
.text:0045D18B and ecx, 0FFh
.text:0045D191 mov eax, dword_47E348[ecx*4]
.text:0045D198 mov ecx, [ebp+arg_0]
.text:0045D19B shl ecx, 8
.text:0045D19E xor eax, ecx
.text:0045D1A0 mov [ebp+arg_0], eax
.text:0045D1A3 inc [ebp+arg_4]
.text:0045D1A6 jmp loc_45D169
.text:0045D1AB ; ---------------------------------------------------------------------------
.text:0045D1AB
.text:0045D1AB loc_45D1AB: ; CODE XREF: sub_45D160+16j
.text:0045D1AB mov eax, [ebp+arg_0]
.text:0045D1AE jmp $+5
.text:0045D1B3 pop edi
.text:0045D1B4 pop esi
.text:0045D1B5 pop ebx
.text:0045D1B6 leave
.text:0045D1B7 retn
.text:0045D1B7 sub_45D160 endp


Can anyone tell me what is going on in the above sub ?

PizzaPan
November 15th, 2005, 07:51
From a quick peek it looks like some kinda crc32 function, cause of the and, 0xFF, and the SHL 8, then the table, but i could be wrong, paste some dwords from the table dword_47E348, we could confirm it, or better yet, scan it with peid, it should find the crc32 pretty easy, and see if it is referenced there.

markh51
November 15th, 2005, 08:21
It is CRC32b...

Can you show me how to change this function so that it will accept the encrypted ID (82 B1 1E E7 2D E5 3A E5)?

Code:

int crc(unsigned *id, unsigned *presult)
{
unsigned total;
unsigned short initialvalue = 0;

total = initialvalue;

do {
total = total<<8 ^ crcTable[(unsigned char)(total>>24 ^ id)];
}

while (currentchar != EOF);

*presult = total;

return 1;
}

drizz
November 15th, 2005, 09:18
Quote:

which takes a 8 byte device ID to generate a 8 byte password...
...so I can enter the device ID to generate the password.

there is nothing to reverse here, simply do what the program does.
Code:
DWORD ID[2],encID[2];
ID[0]^=0xE53AE53A;
ID[1]^=0xE53AE53A;
crc(&ID[0],&encID[0]);
crc(&ID[1],&encID[1]);

markh51
November 15th, 2005, 09:33
I sorry to sound so dumb, but you lost me...

The CRC function which I posted above does not work, I took it from some code which calculated the CRC of a file.

I would appreciate if you could show me in a bit more detail, i'm still on my learning curve

markh51
November 15th, 2005, 13:04
... or does anyone know where I can find a C++ CRC routine which I can use ?

_xhp_
November 15th, 2005, 13:34
h**p://www.boost.org/libs/crc/

drizz
November 15th, 2005, 13:37
Code:

typedef unsigned long DWORD;
typedef unsigned char *PBYTE;

DWORD dword_47E348[256]={};

DWORD sub_45D160(DWORD dwCrc,PBYTE pData,DWORD dwDataLen)
{
DWORD len;
__asm {
loc_45D169:

mov eax, dwDataLen
mov len, eax
dec dwDataLen
cmp len, 0
jz loc_45D1AB
mov eax, pData
xor ecx, ecx
mov cl, [eax]
mov eax, dwCrc
shr eax, 18h
xor ecx, eax
and ecx, 0FFh
mov eax, dword_47E348[ecx*4]
mov ecx, dwCrc
shl ecx, 8
xor eax, ecx
mov dwCrc, eax
inc pData
jmp loc_45D169
loc_45D1AB:
}
return dwCrc;
}

DWORD main(DWORD argc,DWORD *argv)
{
DWORD ID[2],encID[2];

ID[0]=0x22454b8;ID[1]=0x17;
//----------------------------------
ID[0]^=0xE53AE53A;ID[1]^=0xE53AE53A;
encID[0]=sub_45D160(0,&ID[0],4);//check how exactly is data pushed
encID[1]=sub_45D160(0,&ID[1],4);//check how exactly is data pushed

return 0;
}

markh51
November 16th, 2005, 06:18
The code doesn't work as planned...

I had to change: typedef unsigned char *PBYTE;
to: typedef unsigned long *PBYTE; as it was giving warnings.

Also when I step through the original code with softice, dwDataLen is 0x00000400 and dwCrc is the encrypted ID. pData appears to be an address where another 400h table is located.

I copied the table in to source code using HexWorks, but im not sure how to make the required changes to the code.

PizzaPan
November 16th, 2005, 09:06
thats why he told you to check how its being pushed, all the answers is there now, just put it together

Anyways, i sent you a pm about the target, any chance you can reply ?

Cya.

markh51
November 16th, 2005, 09:40
I managed to get the code to do what I want but it crashes at the end.

Code:
DWORD main(DWORD argc,DWORD *argv)
{
DWORD ID[1],encID[1];

ID[0]^=0x3AE53AE5;
ID[1]^=0x3AE53AE5;

encID[0] = CRC(ID[0],dword_47BB94,1024);
encID[1] = CRC(ID[1],dword_47BB94,1024);

printf("%08X", encID[0] & encID[1])

return 1;
}


Can you take a quick peek ?