iCTF 2011. Challenge 30 ($500)

There is encrypted file “reverse2.7z.enc”. So if you look careful you see repeated pattern:

If you look at normal 7z file there are nulls there, so it means that XOR or ADD with DWORD could be there like a crypt algorithm.

When we tried XOR with 0x9012347a and we got 7z archive:

After unpack there are 2 file there: “a” and “b”. At first glance “a” is a code part and “b” is a data. So let’s look at a in IDA. There are two functions:

int __cdecl sub_0(unsigned __int8 *a1)
{
  int result; // eax@1
  int v2; // [sp+0h] [bp-50h]@0
  int v3; // [sp+0h] [bp-50h]@1
  unsigned int i; // [sp+4Ch] [bp-4h]@1
 
  result = v6001A238(0x60011268u, v2);
  for ( i = 0; i < 0x18; ++i )
  {
    v6001A238(0x60011264u, a1[i] % 10 + 48);
    if ( i == 12 )
      v6001A238(0x60011260u, v3);
    result = i + 1;
  }
  return result;
}

And

int __cdecl sub_A0(char *a1)
{
  int result; // eax@3
  unsigned int i; // [sp+4Ch] [bp-4h]@1
  unsigned int j; // [sp+4Ch] [bp-4h]@4
 
  for ( i = 0; i < 0x18; ++i )
  {
    a1[i] = i;
    result = i + 1;
  }
  for ( j = 0; j < 0x18; ++j )
  {
    a1[j] ^= *(_BYTE *)(2 * j + 0x60011288);
    result = j + 1;
  }
  return result;
}

There are several interesting constant:
0x6001A238, 0x60011268, 0x60011264, 0x60011260, 0x60011288
Here I recall you about file “b” which should be data. 0x60011260 is a lowest address which used and if we confront it with 0 offset in file “b” then function sub_0 became more understandable:

  • 0x6001A238 – is a “printf” function.
  • 0x60011260 – pointer to “-”
  • 0x60011264 – pointer to “%c”
  • 0x60011268 – pointer to “Bank account:”

So I rewrite this function:

void print(unsigned char* a1)
{
  printf("Bank account: ");
  for (int i = 0; i < 0x18; ++i )   { 	if (a1[i] % 10 + 48 >= 48)
	   printf("%c", a1[i] % 10 + 48);
	else
		printf("%c", a1[i] % 10 + 48);
	if ( i == 12 )
	  printf("-");
  }
}

Now we know that 0x60011288 is offset 0x28 in file “b” and can rewrite second function:

unsigned char key2[] =
"\x1F\x82\x9D\x23\x3F\x5F\x5C\x59\x17\xF7\x95\xAF
\xEC\x2B\xC6\x5E\x11\xEB\x33\xFE\x35\xF6\xF7\x87
\x28\xAA\xA0\x32\xCE\xA9\x2B\x40\x5E\x42\xCD\x53
\xE7\x07\xD2\x8D\x98\x01\xA1\xE2\x12\x37\x54\xEA";
 
int decrypt(unsigned char *a1)
{
  for (int i = 0; i < 0x18; ++i )
  {
    a1[i] = i;
  }
  for (int j = 0; j < 0x18; ++j )
  {
    a1[j] ^= *(char *)(2 * j + key2);
  }
  return 0;
}

Let’s call them together

int main(int argc, char* argv[])
{
	unsigned char key1[0x18*2];
    	memset(key1,0,0x18*2);
	decrypt(key1);
	print(key1);
}

C:\ctf\~writeups\ictf2011\challenge30\keygen\debug>keygen.exe
Bank account: 1615944358326-32680530047

1 ping

  1. […] More (Challenges 29, 30, 31, 32, […]

Leave a Reply

Your email address will not be published.