ThatGuyPT 457 Posted November 25, 2013 Boas pessoal. Ontem e hoje andei a trabalhar no meu ultimo sistema que permite proteger o vosso software desenvolvido em C++ . Este software não é o novo grito, no entanto serve muito bem para o que precisam. #pragma comment(lib, "Ws2_32.lib")#include <winsock2.h>#include <iostream>#include <string>#include <sstream>#define recvBuffSize 2000const std::string host = "multicraft.proficyhost.com", page = "hwid2.txt";int main(int argc, char* argv[]){ //HWID Check Starts Here HW_PROFILE_INFO hwid; WSADATA wsData; if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) return 1; SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { WSACleanup(); return 1; } int check, i = 0; hostent *dns; char recieve[recvBuffSize]; //Webrequest para ir buscar o conteúdo do documento .txt sockaddr_in sin; sin.sin_addr.S_un.S_addr = inet_addr(host.c_str()); sin.sin_family = AF_INET; sin.sin_port = htons(80); std::string req; memset(&req, 0, sizeof(req)); memset(&recieve, 0, sizeof(recieve)); req = "GET /" + page + " HTTP/1.1rnHOST: " + host + "rnUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)rnConnection: Closernrn"; if (sin.sin_addr.s_addr == INADDR_NONE) { dns = gethostbyname(host.c_str()); if (dns == NULL) return 1; while (dns->h_addr_list[i]) { //Loop nas resoluções do hostname sin.sin_addr.s_addr = *(unsigned int*)(dns->h_addr_list[i]); check = connect(sock, (sockaddr*)&sin, sizeof(sin)); if (check == SOCKET_ERROR) i++; else break; } } else { check = connect(sock, (sockaddr*)&sin, sizeof(sin)); if (check == SOCKET_ERROR) return 1; } check = send(sock, req.c_str(), req.size(), NULL); if (check == SOCKET_ERROR) { std::cout << WSAGetLastError(); std::cin.get(); WSACleanup(); return 1; } recv(sock, recieve, sizeof(recieve), NULL); WSACleanup(); std::string final = recieve; //conversao char* para string para usar funções especificas (erase, replace etc) int x, nume, countline = 0; char hwidlist[255][8]; int pos, lineact; int line = 0; //APAGA AS INFORMAÇÕES RELATIVAS Á WEBREQUEST (Header enorme a ignorar) for (x = 0; i < final.length(); x++) if (final.at(x) == 'r' && final.at(x + 1) == 'n' && final.at(x + 2) == 'r' && final.at(x + 3) == 'n') break; final.erase(0, x + 4); // nume = 0; int cv = 0; countline = 0; //Escrever os IDs da string recebida do servidor para um vector para mais fácil acesso while (nume < final.length()){ if (final.at(nume) != 'n' && final.at(nume) != 'r'){ hwidlist[line][cv] = final.at(nume); cv++; } if (final.at(nume) == 'n' || final.at(nume) == 'r'){ line++; countline++; cv = 0; } nume++; } // //Hard Disk ID Grabber DWORD dwSerial; std::stringstream ss; std::stringstream ss2; std::string ret; if ( !GetVolumeInformation("C:", NULL, 0, &dwSerial, NULL, NULL, NULL, 0 ) ) { ss << "Error: " << GetLastError(); } else { ss << dwSerial; int x = atoi( ss.str().c_str() ); char hex[64]; _snprintf( hex, sizeof( hex ) -1, "%x", x ); ret = hex; } char *dataa; dataa = reinterpret_cast<char *>( strdup( ret.c_str() ) ); int countright; bool continuar = true; int linh, car; //Comparar o Hard Disk ID com os IDs presentes no nosso documento .txt no servidor for(linh = 0; linh <= countline; linh++){ if(continuar == true){ // DEBUG std::cout << "Linha " << linh << std::endl; countright = 0; for (car = 0; car <= 8; car++){ if (hwidlist[linh][car] == dataa[car]){ countright++; // DEBUG std::cout << "Caracter certo na linha " << linh << " Certos ate agora:" << countright << std::endl; } } if(countright == 8){ continuar = false; // DEBUG std::cout << "Parou" << std::endl; } } } if (countright == 8){ // DEBUG std::cout << "Caracteres Certos: " << countright << std::endl; // DEBUG std::cout << "Numero de Linhas: " << countline+1 << std::endl; std::cout << "HWID Authentication Sucessful, Access Granted." << std::endl; //AQUI FICARÁ LOCALIZADO O NOSSO PROGRAMA PRINCIPAL } else{ // DEBUG std::cout << "Caracteres Certos: " << countright << std::endl; // DEBUG std::cout << "Numero de Linhas: " << countline+1 << std::endl; std::cout << "Your HWID:" << dataa << std::endl; std::cout << "HWID Unsuccessful, Access Blocked." << std::endl; // DEBUG std::cout << final << std::endl; // DEBUG std::cout << "MEU ID: " << dataa[0] << dataa[1] << dataa[2] << dataa[3] << dataa[4] << dataa[5] << dataa[6] << dataa[7] << std::endl; // DEBUG std::cout << "IDs no ficheiro:" << std::endl; // std::cout << hwidlist[0][0] << hwidlist[0][1] << hwidlist[0][2] << hwidlist[0][3] << hwidlist[0][4] << hwidlist[0][5] << hwidlist[0][6] << hwidlist[0][7] << std::endl; // std::cout << hwidlist[1][0] << hwidlist[1][1] << hwidlist[1][2] << hwidlist[1][3] << hwidlist[1][4] << hwidlist[1][5] << hwidlist[1][6] << hwidlist[1][7] << std::endl; // std::cout << hwidlist[2][0] << hwidlist[2][1] << hwidlist[2][2] << hwidlist[2][3] << hwidlist[2][4] << hwidlist[2][5] << hwidlist[2][6] << hwidlist[2][7] << std::endl; } std::cin.get(); //HWID Check ends here return 0;} Código extremamente desorganizado, eu sou horrivel com as variáveis, deixei ainda as mensagens usadas para debugging, funciona um pouco como proof of concept essas instruções comentadas. Eu implementei isto no meu hack que é uma .DLL e nesta por exemplo caso detecte que o HWID (neste caso é o Serial do Disco-Rigido) não está presente no ficheiro .txt hwid.txt do servidor pretendido simplesmente faz a função RemoveHooks(); int WINAPI RemoveHooks(){ hookedD3D9.CleanUp(); HookVTableFunction<Reset_t>(dwpVTableStart,16,(DWORD)oReset); HookVTableFunction<Present_t>(dwpVTableStart,17,(DWORD)oPresent); HookVTableFunction<Reset_t>(dwpDeviceVMT,16,(DWORD)oReset); HookVTableFunction<Present_t>(dwpDeviceVMT,17,(DWORD)oPresent); Sleep(1000); return 0;} O que esta faz é basicamente não mostrar mais o menu do hack no ecrã logo a .DLL continua injetada sem ter qualquer função. Podem usar ao vosso gosto. Exploits: Indo ao ficheiro de hosts do windows e alterando o host onde vão buscar o documento txt para um website qualquer onde tenha um ficheiro com o mesmo nome e com o HWID das pessoas é possível burlar o sistema. Como Melhorar: Não é totalmente segura esta forma de gerar o HWID, a minha recomendação é algo do género de: md5(Disk ID + CPU ID + salt);. Devido à maneira fácil de explorar a falha através do ficheiro de hosts do windows há uma maneira de arranjar. O conceito é o mesmo dum chat em c++, fazemos uma API para verificar numa base de dados MySQL, mas isto requer uma VPS/Dedicado. Consiste em ter um servidor que recebe os HWIDs dos clientes e verifica-os na base de dados MySQL, se existir retorna a duração da licença e que existe. É muito fácil dar exploit numa falha que usa um ficheiro .txt numa página web mas muito dificil emular os pacotes recebidos em retorno, pelo que é quase impossivel contornar se feito dessa maneira. Não façam ligação direta a uma base de dados porque através de reverse engineering é possivel ter acesso á base de dados e password. Recomendo a darem pack no vosso executável com Themida/Enigma Protector para maximizar a segurança. (Agradecimentos ao GunnerMBT pelas ideias) Não irei fornecer nenhuma das melhorias indicadas, eu forneço a base e trabalham-na como quiserem, algo que fosse tão seguro como o que eu falei não poderia ser publicado publicamente gratuitamente. Comentei o código para explicar melhor. 6 p0w3r0ff, Gemeos, NewWars and 3 others reacted to this Share this post Link to post Share on other sites
Gemeos 0 Posted February 4, 2017 Bem que você poderia deixar essa source em download. Não estou conseguindo montar a base. Share this post Link to post Share on other sites