Cracking X-Chat — part ii
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.
man, que cena de sonho, keygenar open sores!
Trying to make money with GNU ... [ FAIL ]