9

[原创]看雪2016 第二十五题 CrackMe逆向分析

HighHand 2017-1-1 22:10 2458
该题作者使用了base32和camellia算法,定位算法使用了特征值 0xA09E667F,0x3BCC908B。该值用于camellia算法的key扩展中。

通过WM_GETTEXT获取sn字符串,如下
004032E5  |.  66:898424 450>mov     word ptr [esp+145], ax           ; |
004032ED  |.  888424 470100>mov     byte ptr [esp+147], al           ; |
004032F4  |.  A1 08A24200   mov     eax, dword ptr [42A208]          ; |
004032F9  |.  6A 0D         push    0D                               ; |Message = WM_GETTEXT
004032FB  |.  50            push    eax                              ; |hWnd => NULL
004032FC  |.  C68424 3C0100>mov     byte ptr [esp+13C], 0            ; |
00403304  |.  FF15 08F14100 call    dword ptr [<&USER32.SendMessageA>; \SendMessageA
0040330A  |.  83F8 23       cmp     eax, 23
0040330D  |.  0F85 D0010000 jnz     004034E3


且sn长度为0x23个字符
00403322  |> /0FBE88 E08E42>|/movsx   ecx, byte ptr [eax+428EE0]
00403329  |. |3BF1          ||cmp     esi, ecx
0040332B  |. |74 08         ||je      short 00403335
0040332D  |. |40            ||inc     eax
0040332E  |. |83F8 03       ||cmp     eax, 3
00403331  |.^\72 EF         |\jb      short 00403322
00403333  |.  EB 15         |jmp     short 0040334A
00403335  |>  0FBE90 E08E42>|movsx   edx, byte ptr [eax+428EE0]
0040333C  |.  80BC14 580100>|cmp     byte ptr [esp+edx+158], 4C      ;  'L'
00403344  |.  0F85 99010000 |jnz     004034E3
0040334A  |>  83F8 03       |cmp     eax, 3


sn 位置 08 11 1A 的字符必须为 ‘L’
004033A0  |.  8D4C24 14     lea     ecx, dword ptr [esp+14]
004033A4  |.  51            push    ecx
004033A5  |.  8D9424 440100>lea     edx, dword ptr [esp+144]
004033AC  |.  52            push    edx
004033AD  |.  8D8424 840100>lea     eax, dword ptr [esp+184]
004033B4  |.  50            push    eax
004033B5  |.  8D4C24 24     lea     ecx, dword ptr [esp+24]
004033B9  |.  51            push    ecx
004033BA  |.  E8 31CE0000   call    004101F0

调用 004101F0 对剩余sn部分进行 base32 解码,长度为 0x14

004033D6  |.  50            push    eax                              ; /String
004033D7  |.  FF15 10F04100 call    dword ptr [<&KERNEL32.lstrlenA>] ; \lstrlenA
004033DD  |.  50            push    eax
004033DE  |.  8DBC24 A40100>lea     edi, dword ptr [esp+1A4]
004033E5  |.  E8 F6FAFFFF   call    00402EE0
004033EA  |.  83C4 08       add     esp, 8

通过 cnbragon@pediyctf2016 生成 a,a长度为0x20

00403454  |.  0FAFC5        imul    eax, ebp
00403457  |.  0FAF8424 5402>imul    eax, dword ptr [esp+254]
0040345F  |.  0FAFC6        imul    eax, esi
00403462  |.  0FAFC7        imul    eax, edi
00403465  |.  0FAFC1        imul    eax, ecx
00403468  |.  0FAFC2        imul    eax, edx
0040346B  |.  899C24 CC0100>mov     dword ptr [esp+1CC], ebx
00403472  |.  398424 500100>cmp     dword ptr [esp+150], eax


a 转换到 DWORD,计算乘积
v0 = a[7] * a[0] * a[6] * a[1] * a[5] * a[2] * a[4] * a[3];
这里 v0需要为 61B45600即sn的最后一部分,才能通过

        v54 = a[0] + a[7];
        v55 = a[1] + a[6];
        v56 = a[2] + a[5];
        v57 = a[3] + a[4];
求和结果作为 camellia算法的 key进行初始化(key扩展),
0040347B  |.  8D4424 18     lea     eax, dword ptr [esp+18]
0040347F  |.  8D9424 C00100>lea     edx, dword ptr [esp+1C0]
00403486  |.  E8 75DBFFFF   call    00401000			; Camellia_Ekeygen
0040348B  |.  8BC8          mov     ecx, eax

0040348D  |.  51            push    ecx
0040348E  |.  8DB424 300100>lea     esi, dword ptr [esp+130]
00403495  |.  8D8C24 440100>lea     ecx, dword ptr [esp+144]
0040349C  |.  E8 BFF2FFFF   call    00402760			; Camellia_DecryptBlock
004034A1  |.  83C4 04       add     esp, 4
004034A4  |.  B8 10000000   mov     eax, 10
004034A9  |.  33C9          xor     ecx, ecx
004034AB  |.  EB 03         jmp     short 004034B0

对 sn解码后的数据进行 解密,大小为 0x10

004034B0  |>  8B940C 2C0100>/mov     edx, dword ptr [esp+ecx+12C]
004034B7  |. |3B940C 500200>|cmp     edx, dword ptr [esp+ecx+250]
004034BE  |. |75 23         |jnz     short 004034E3
004034C0  |. |83E8 04       |sub     eax, 4
004034C3  |. |83C1 04       |add     ecx, 4
004034C6  |. |83F8 04       |cmp     eax, 4
004034C9  |.^\73 E5         \jnb     short 004034B0
004034CB  |.  A1 0CA24200   mov     eax, dword ptr [42A20C]
004034D0  |.  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
004034D2  |.  68 A08E4200   push    00428EA0                         ; |Title = "Success!"
004034D7  |.  68 AC8E4200   push    00428EAC                         ; |Text = "Congratulations! ",LF," You will be the keygen machine!"
004034DC  |.  50            push    eax                              ; |hOwner => 001904CC ('#KeygenMe#',class='#32770')
004034DD  |.  FF15 0CF14100 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA

将解码结果与 指定数据(A8 27 F7 4B 09 79 23 C9 C9 6B 97 95 EB E6 92 38)进行比较,通过后提示成功。

主要代码如下:
#include "stdafx.h"
#include <memory.h>

#include "camellia.h"

char * gb32 = "ABCDEFGHJKMNPQRSTVWXYZ1234567890";

int base32_decode(char *sn, unsigned char *buf, int *len)
{
	char code[256];
	memset(code, 0xFF, 256);
	for (int j = 0; j < 32; j++)
	{
		code[gb32[j]] = j;
	}

	int k = 8; // 剩余 bits
	int i = 0; int j = 0;
	while (sn[i])
	{
		char ch = sn[i];
		int a = code[ch];
		
		if (k >= 5)
		{
			k = k - 5;
			buf[j] |= (a << k);
			if (k == 0)
			{
				j++;
				k = 8;
			}
		}
		else
		{
			k = 5 - k;
			buf[j++] |= (a >> k);
			k = 8 - k;
			buf[j] = (a << k);
		}

		i++;
	}
	return 0;
}

int base32_encode(unsigned char *buf, int len, char *sn)
{
	char code[256];
	memset(code, 0xFF, 256);
	for (int j = 0; j < 32; j++)
	{
		code[gb32[j]] = j;
	}

	int k = 8;
	int i = 0; int j = 0;
	while (i < len)
	{
		int ch = 0;

		if (k >= 5)
		{
			k -= 5;
			ch = (buf[i] >> k) & 0x1F;
			if (k == 0)
			{
				i++;
				k = 8;
			}
		}
		else
		{
			k = 5 - k;
			ch = (buf[i] << k) & 0x1F;
			i++;
			k = 8 - k;
			ch |= buf[i] >> k;
		}

		for (int x = 0; x < 256; x++)
		{
			if (code[x] == ch)
			{
				sn[j++] = x;
				break;
			}
		}
	}

	return 0;
}


void camellia_setkey(camellia_ctx *ctx, const unsigned char *key, int bits)
{

	Camellia_Ekeygen(bits, key, ctx->subkey);
	ctx->bits = bits;
}

void camellia_decrypt(const camellia_ctx *ctx, const unsigned char *src, unsigned char *dst)
{

	Camellia_DecryptBlock(ctx->bits, src, ctx->subkey, dst);
}

void camellia_encrypt(const camellia_ctx *ctx, const unsigned char *src, unsigned char *dst)
{

	Camellia_EncryptBlock(ctx->bits, src, ctx->subkey, dst);
}

int _tmain(int argc, _TCHAR* argv[])
{
	unsigned int b[6] = { 0 };
	char *sn = "11111111111111111111111111111111";
	//char *sn = "ABCDEFGHJKMNPQRSTVWXYZ1234567890";
	base32_decode(sn, (unsigned char *)b, 0);

	char buf[64] = { 0 };

	b[4] = 0x61B45600;
	base32_encode((unsigned char *)b, 0x14, buf);
	printf("%s\n", buf);

	camellia_ctx ctx = { 0 };
	unsigned char key[16] = {
		0xA2, 0x7F, 0x82, 0x60, 0xB5, 0x91, 0x62, 0x54, 0x17, 0x06, 0x14, 0xEB, 0x60, 0xA2, 0xDB, 0x1F
	};
	camellia_setkey(&ctx, key, 128);

	unsigned char v[16] = {
		0xA8, 0x27, 0xF7, 0x4B, 0x09, 0x79, 0x23, 0xC9, 0xC9, 0x6B, 0x97, 0x95, 0xEB, 0xE6, 0x92, 0x38
	}; 

	int buf2[64] = { 0 };
	buf2[4] = 0x61B45600;

	//camellia_decrypt(&ctx, v, (unsigned char *)buf2);
	camellia_encrypt(&ctx, v, (unsigned char *)buf2);

	base32_encode((unsigned char *)buf2, 0x14, buf);
	printf("%s\n", buf);

	return 0;
}



sn=981C2H7QLAZZ009EJL79BT2BSCLVTAFQQDB
最新回复 (2)
wendax 2017-1-1 22:20
2
感谢楼主的帖子,
万能的群主 2017-1-3 08:42
3
虽然没怎么看懂,但是还是觉得算法要好好学习了
返回