Mais um blog inútil.

Abril 17, 2008

Cracking X-Chat — part ii

Filed under: Coding,Cracking,Drama,Fail,Useless — dongs @ 23:21

Aparentemente saiu uma nova versão do xcrap, 2.8.7a. Eu reparei nisto e lembrei-me que houve um post do falso ha uns tempos que falava de como crackar opensores. Infelizmente, não tenho muito tempo por isso vou ser sucinto.

O leitor assíduo facilmente vai descompactar o executável (é uma versão antiga do UPX) e encontrar a função de interesse (sub_4018CD).

Aqui encontramos o algoritmo de verificação, que consiste essencialmente em:

Hash = SHA-1(Linha3|Linha4|Linha4)

E = 0x25F86508483EFD

N = 0xB5BA27D856CCBE6B61CFE96A387D8E265A65897510AE91212634A7397432D1B2407604CAFA9DC77EF29A87B86D938748E0C4921D46C3AC4BCE7E00EECDFCF782DBD0D44C46C9057724CCF7DEDF36924E4683721FF55EDC570C4C71927887D67C1B1488A33E0B3F64160701B2390C3B3F278490B22DE9906A65B9DFBDF4E838870EFD5851DC0B2C94E444E0B1D2DAAA5C6060D3976E170BB8692111E26D178871008AE42EE250A856D2354102B57F560420AC9F89D004AF761341764FBEDD194A27AF6F34B9C0E3A48013734C6CBD3C216CFAD9B1F3DFDB76FE8519C78E3E95F3C4B39006111DE983C88D72CD4613D4CB852D36244D7B8D4AB15C740415382735

GoodSignature = 00 01 FF FF ... (tem de ter 256 bytes (2048 bit) ... FF FF 00 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 | Hash

if (Linha2 ^ E (mod N) == GoodSignature) return GOOD else return BAD

OK, então temos basicamente uma assinatura digital baseada em RSA com 2048 bits. Não existem exploits óbvias (padding, expoente baixo, ...) que se possam aproveitar; portanto, para fazer um keygen temos de alterar a chave pública. Escolham uma e substituam no sítio apropriado (public_key_n). Para gerar uma chave válida, temos então:

void generate_key(void)

{

char LInha1[] = "# Designed and implemented exclusively for the lulz";

char Linha2[1024];

char Linha3[] = "Some Jew";

char Linha4[] = "Crap";

char Linha5[] = "More crap";

HCRYPTPROV hProv;

HCRYPTHASH hHash;

unsigned char appendage[] = {00, 30, 21, 30, 09, 06, 05, 2B, 0E, 03, 02, 1A, 05, 00, 04, 14};

unsigned char good_signature[256];

unsigned char sha[32];

unsigned long tmp = 20;

mpz_t n, d, c;

memset(Linha2, 0, sizeof(Linha2)*sizeof(Linha2[0]));

CryptAcquireContext(&hProv, 0, 0, 1, 0xF0000000);
CryptCreateHash(hProv, 0x00008004, 0, 0, &hHash);
CryptHashData(hHash, Line3, strlen(Line3), 0);
CryptHashData(hHash, Line4, strlen(Line4), 0);
CryptHashData(hHash, Line5, strlen(Line5), 0);
CryptGetHashParam(hHash, 2, sha, &tmp, 0);
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);

memset(good_signature, 0xFF, 256);

memcpy(good_signature+220, appendage, sizeof(appendage));

memcpy(good_signature+236, sha, 20);

good_signature[0] = 0;

good_signature[1] = 1;

mpz_init_set_str(n, "9AFF449090074D691910719D0B384FDA86FAB987938E74CB6E6A91BE6086A8E11BDBD2EF7C1F3761EEBC3AB171F2FB9A79BD8A3CFBAD54A707F39FB8E804A0F4874447BE66550E9D444C496D251FF2402DC8DBAD7352124633F5CAF43A3971362B4466F28AAB1C2A1E81F36B8EE5E6284DD9645E500083B0B9102D559A57A52F0E831F7B39B630DC9B479E3914F34F33363A2075F372E650B94D230528A998D1613C097D78C1C66AE647E0DCF9590E3CA012C3A26614F851AE520163699044F6E8F71B8EDA7091DFDB4745FE27A806EF56E6B7B7175B7859B1725ACF6A03CC941DFED8773AA02DF350C3C0479744411B7F1CD625F5BF4F76E38DD42AC4901A89", 16);

mpz_init_set_str(d, "36C70BF3DDBD70026346284E9E40E0B1637DD2FF8506F959772CBCEE7F2613A8697D8B822C6849753541DFAECA891A50C0F515E42F1BC8DFF2F48452BA27D29602E572DC9676512F1631AEF655C8F37C03C9E9E5E532CABE4ABD0E0495FA1556AC484D2F5F6E8AF08F934C80CC8D0369215FA2E5F73C0648509867BE61B766C716D84934F76699FAD81EC04E78E88CCC592D59B183361F35B2F3A0F2FEDC17F94F73831111984E5AB2AFCCC019090E4A48AB6CFE249066EFA6D02A4A9EA8369E60EF45A2CC921AE66C52CA1D273EB0355BAC9FD7598258FF94ED311100E732D22224B3744C3ABBB6BA4995781B8427D2BBF605488AC20E19483C10894283506D", 16);

mpz_init(c);

mpz_powm(c, c, d, n);

printf("%s\n", Linha1);

gmp_printf("%Zd\n", c);

printf("%s\n", Linha3);

printf("%s\n", Linha4);

printf("%s\n", Linha5);

mpz_clear(n);

mpz_clear(d);

mpz_clear(c);

}

Disclaimer: este código foi feito de cabeça e nem sequer o tentei compilar. Se não funcionar, DESCUBRAM porquê!

Note-se que o autor implementou duas verificações para prevenir a alteração do executável (e assim também, da chave).

Primeira:

UPX0:004081EE loc_4081EE: ; CODE XREF: sub_4081BA+45j
UPX0:004081EE movzx edi, ds:public_key_n[ecx]
UPX0:004081F5 add edi, edx
UPX0:004081F7 shl edi, 1
UPX0:004081F9 inc ecx
UPX0:004081FA cmp ecx, 40h
UPX0:004081FD mov edx, edi
UPX0:004081FF jb short loc_4081EE
UPX0:00408201 cmp edx, 0B3A690A6h
UPX0:00408207 pop edi
UPX0:00408208 jz short loc_40822B

Segunda:

UPX0:00425A7A loc_425A7A: ; CODE XREF: sub_425A14+74j
UPX0:00425A7A movzx edx, byte ptr [eax]
UPX0:00425A7D imul ecx, 1Fh
UPX0:00425A80 add ecx, edx
UPX0:00425A82 dec eax
UPX0:00425A83 cmp eax, offset sub_401000
UPX0:00425A88 jnz short loc_425A7A
UPX0:00425A8A cmp ecx, 1D9AB667h
UPX0:00425A90 jz short locret_425A98

Certifiquem-se que corrigem isto quando alterarem o executável.

Já agora, a IDB comentada.

Um bem haja para todos.

Um comentário a “Cracking X-Chat — part ii”

  1. falso diz:

    man, que cena de sonho, keygenar open sores!

    Trying to make money with GNU ... [ FAIL ]

Comentar

widgeon
widgeon
widgeon
widgeon