Removed stuff which hasn't been used anymore

This commit is contained in:
WolverinDEV 2020-01-24 02:40:30 +01:00
parent 14bfda467f
commit bf689eca59
28 changed files with 15 additions and 4250 deletions

View File

@ -1,12 +1,11 @@
cmake_minimum_required(VERSION 3.6)
project(TeaSpeak-Parent)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/Modules")
set(TEASPEAK_SERVER ON)
set(CMAKE_VERBOSE_MAKEFILE ON)
#end now
#set(MEMORY_DEBUG_FLAGS " -fsanitize=leak -fsanitize=address -fstack-protector-all ")
#set(MEMORY_DEBUG_FLAGS "-fsanitize=address")
@ -71,9 +70,7 @@ set(LIBRARY_PATH_GLIBC "${GLIBC_LIB_DIR}/libgio-2.0.a;${GLIBC_LIB_DIR}/libgmodul
add_definitions(-DINET -DINET6)
add_subdirectory(shared/)
add_subdirectory(client/)
add_subdirectory(server/)
add_subdirectory(license/)
add_subdirectory(flooder/)
add_subdirectory(MusicBot/)
add_subdirectory(music/)

View File

@ -1,79 +0,0 @@
cmake_minimum_required(VERSION 3.6)
project(TeamSpeak)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -static-libgcc -static-libstdc++ -pthread ${MEMORY_DEBUG_FLAGS}")
include_directories(../shared/src)
add_definitions(-DLTM_DESC)
set(SOURCE_FILES
main.cpp
src/protocol/Connection.cpp
src/protocol/ConnectionHandschake.cpp
src/protocol/ConnectionPacketHandler.cpp
src/protocol/socket/FilteredUDPSocket.cpp
src/protocol/socket/RawUDPSocket.cpp
src/Identity.cpp
src/MultithreadedIdentity.cpp
src/protocol/HandshakeNew.cpp
../shared/src/License.cpp
)
find_package(Protobuf REQUIRED)
include_directories(${Protobuf_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS proto/LicenseKey.proto)
add_executable(TeamSpeakClient ${SOURCE_FILES} ${PROTO_SRCS})
target_link_libraries(TeamSpeakClient
${LIBRARY_PATH_THREAD_POOL} #Static
TeaSpeak #Static
TeaLicenseHelper #Static
TeaMusic #Static
${LIBRARY_PATH_TERMINAL} #Static
${LIBRARY_PATH_VARIBALES}
${LIBRARY_PATH_YAML}
pthread
stdc++fs
${LIBEVENT_PATH}/libevent.a
${LIBEVENT_PATH}/libevent_pthreads.a
opus.a
${LIBRARY_PATH_JSON}
${LIBRARY_PATH_PROTOBUF}
DataPipes
#${LIBWEBRTC_LIBRARIES} #ATTENTIAN! WebRTC does not work with crypto! (Already contains a crypto version)
${LIBRARY_TOM_CRYPT}
${LIBRARY_TOM_MATH}
#We're forsed to use boringssl caused by the fact that boringssl is already within webrtc!
#Require a so
sqlite3
${LIBRARY_PATH_ED255}
${LIBRARY_PATH_BREAKPAD}
${LIBRARY_PATH_JDBC}
${LIBRARY_PATH_PROTOBUF}
${LIBRARY_PATH_BORINGSSL_SSL}
${LIBRARY_PATH_BORINGSSL_CRYPTO}
)
#strip -s -p -v TeamSpeakHash
add_executable(TeamSpeakHash src/Identity.cpp src/MultithreadedIdentity.cpp identityHash.cpp)
#set_target_properties(TeamSpeakHash PROPERTIES CMAKE_CXX_FLAGS "-o1")
target_link_libraries(TeamSpeakHash
TeaSpeak
ThreadPoolStatic
pthread
${TOM_LIBRARIES}
${LIBRARY_TOM_CRYPT}
${LIBRARY_TOM_MATH}
${LIBRARY_PATH_BORINGSSL_SSL}
${LIBRARY_PATH_BORINGSSL_CRYPTO}
)

View File

@ -1,29 +0,0 @@
#pragma once
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#define CRYPT_MACRO(r, d, i, elem) ( elem ^ ( d - i ) )
#define DEFINE_HIDDEN_STRING(NAME, SEED, SEQ)\
static const char* BOOST_PP_CAT(Get, NAME)()\
{\
static char data[] = {\
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH_I(CRYPT_MACRO, SEED, SEQ)),\
'\0'\
};\
\
static bool isEncrypted = true;\
if ( isEncrypted )\
{\
for (unsigned i = 0; i < ( sizeof(data) / sizeof(data[0]) ) - 1; ++i)\
{\
data[i] = CRYPT_MACRO(_, SEED, i, data[i]);\
}\
\
isEncrypted = false;\
}\
\
return data;\
}

View File

@ -1,27 +0,0 @@
[OUT] clientinitiv alpha=kXZSTZ7qaOhblA== omega=MEwDAgcAAgEgAiA5+ycSoMRRdugndbohYtH7PqS6Q6h3TV1VnGRKoZNMsQIhANn2rszHVipB13LBcY2Zf3APg7HX7ix3WWiaT5hjQrUv ot=1 ip=84.200.62.248
[ IN] initivexpand2 l=AQCBIiOUkbXLeQ\/6UhNB+8iJnwLYGZJglZoDFSTt+7awWgAJFtlwLxmo8AAAACVUZWFtU3BlYWsgU3lzdGVtcyBHbWJIAADtwskuiFg0FkafvNvS1uwz67b2lEhMnOkAygPvo0waGAAJQrh2HBxqvQAAACRUZWFtU3BlYWsgc3lzdGVtcyBHbWJIAADd85KDiA8UeqB5G9MBtNZ879CYBnfbjc\/OVj0j0xMcqQIJQ7qACi5lgAYAAAAAVGVhbVNwZWFrIFN5c3RlbXMgR21iSAAAitZK9P6JEXiiy+uERaapfw\/I5na7S5M+Se5IoOb\/24kgCV6OnAlfN1w= beta=5cB\/vUHLQ7GbVPNRStMLnZlyo572IFPzdgTTgxJ3zF4JBehh7nLudpdzk1hdbcglx4n3JmqX omega=MEwDAgcAAgEgAiEA83r2Er9vHr5sSEcm9g\/\/rdLjOdTMtwX\/Lkbi02+24FkCIB2P804l26yketcG8WxZQJ1z4ukU0e3SqEzm4pKHzMRY ot=1 proof=MEUCIAgYSvrPo0OKKD8aRmjeKVS1EVF6L\/DXLBT+XFkZlMVPAiEAnSMVOp8DOEMzcE42hna72+aWr+Z4+a76x23hmDJa4Uk= tvd=AQAAAABaQjKEblQQgGczKfB+CSS7IY5qli8LRS9jDltkab8leo6ltwQH82VUU\/WwnpCbazVbnh4iNbcobdxv\/MTX5Y3+6xpqDgEAEa1\/SLpE\/CIg2X7GX9mtDCCvP1KdQGaT\/RKoofPSsTkACRbZcAr4DPAAAAASVGVhbVNwZWFrIFN5c3RlbXMgR21iSAAAPgFaQLsu0h3FTQax+i0qXFXX\/Bn7VcGJH8SE5AOAiuQECVvUYwlenQk= time=1514211836
[OUT] clientek ek=n4+LesWAJf+8ha6LlF5kWilUbj59qX+zV31asaniK8U= proof=MEQCIC+NxeqTNUQWqHz914BHkFfC3LTF8BkYAYktMB62sET7AiBPmnfN6yoB381g\/GAnZVwMkeCPIjKi9vHUk15yOdT5FQ==
[OUT] clientinit client_nickname=P3nisBaum client_version=3.1.7\s[Build:\s1513163251] client_platform=Windows client_input_hardware=1 client_output_hardware=1 client_default_channel client_default_channel_password client_server_password client_meta_data client_version_sign=tdNngCAZ1ImAf7BxJzO4RXv5nBRsUERsrSOnMKVUFNQg6BS4Bzag0RFgLVzs2DRj19AC8+q5cXgH+5Ms50mTCA== client_key_offset=15848377 client_nickname_phonetic client_default_token client_badges=Overwolf=0 hwid=3036580947951600a7de06cd796bb0f1,7209e96ac1f60ff7772b7301919e0878
[OUT] clientinit client_nickname=P3nisBaum client_version=3.1.7\s[Build:\s1513163251] client_platform=Windows client_input_hardware=1 client_output_hardware=1 client_default_channel client_default_channel_password client_server_password client_meta_data client_version_sign=tdNngCAZ1ImAf7BxJzO4RXv5nBRsUERsrSOnMKVUFNQg6BS4Bzag0RFgLVzs2DRj19AC8+q5cXgH+5Ms50mTCA== client_key_offset=15848377 client_nickname_phonetic client_default_token client_badges=Overwolf=0 hwid=3036580947951600a7de06cd796bb0f1,7209e96ac1f60ff7772b7301919e0878
[ IN] error id=521 msg=too\smany\sclones\salready\sconnected
-> ot & ip needs to be set
-> ack needs to be unencripted as look clientinitiv not done
initivexpand2 l=AQCBIiOUkbXLeQ\/6UhNB+8iJnwLYGZJglZoDFSTt+7awWgAJFtlwLxmo8AAAACVUZWFtU3BlYWsgU3lzdGVtcyBHbWJIAADtwskuiFg0FkafvNvS1uwz67b2lEhMnOkAygPvo0waGAAJQrh2HBxqvQAAACRUZWFtU3BlYWsgc3lzdGVtcyBHbWJIAADd85KDiA8UeqB5G9MBtNZ879CYBnfbjc\/OVj0j0xMcqQIJQ7qACi5lgAYAAAAAVGVhbVNwZWFrIFN5c3RlbXMgR21iSAAA5Szd\/YkuL5NUF7SeHfvSKi5byOOMvYME0\/WRwlTHK8ogCV6hYglfSiI= beta=W\/D9NTwuZi6L1sbFpA+KiDBMSgl8y6Jy6vFVSGszJy1BPy8zEhNDQ62msazyAgk0CdbY0B+E omega=MEwDAgcAAgEgAiEA83r2Er9vHr5sSEcm9g\/\/rdLjOdTMtwX\/Lkbi02+24FkCIB2P804l26yketcG8WxZQJ1z4ukU0e3SqEzm4pKHzMRY ot=1 proof=MEUCIA3dgrIlXFIjkLrxJ1Yni7OqQYwPing03Xz\/zkQFrmdHAiEA8a0delCktJ21TIrj91QZbA76vtZUL38XVm+P2bR9M7c= tvd=AQAAAABaQjKEblQQgGczKfB+CSS7IY5qli8LRS9jDltkab8leo6ltwQH82VUU\/WwnpCbazVbnh4iNbcobdxv\/MTX5Y3+6xpqDgEAEa1\/SLpE\/CIg2X7GX9mtDCCvP1KdQGaT\/RKoofPSsTkACRbZcAr4DPAAAAASVGVhbVNwZWFrIFN5c3RlbXMgR21iSAAAPgFaQLsu0h3FTQax+i0qXFXX\/Bn7VcGJH8SE5AOAiuQECVvUYwlenQk= time=1514216642
Nr 1
[OUT] clientinitiv alpha=DBiidVqi8kTYAQ== omega=MEwDAgcAAgEgAiA5+ycSoMRRdugndbohYtH7PqS6Q6h3TV1VnGRKoZNMsQIhANn2rszHVipB13LBcY2Zf3APg7HX7ix3WWiaT5hjQrUv ot=1 ip=84.200.62.248
[ IN] initivexpand2 l=AQCBIiOUkbXLeQ\/6UhNB+8iJnwLYGZJglZoDFSTt+7awWgAJFtlwLxmo8AAAACVUZWFtU3BlYWsgU3lzdGVtcyBHbWJIAADtwskuiFg0FkafvNvS1uwz67b2lEhMnOkAygPvo0waGAAJQrh2HBxqvQAAACRUZWFtU3BlYWsgc3lzdGVtcyBHbWJIAADd85KDiA8UeqB5G9MBtNZ879CYBnfbjc\/OVj0j0xMcqQIJQ7qACi5lgAYAAAAAVGVhbVNwZWFrIFN5c3RlbXMgR21iSAAALYVev\/rqwinxd2zrGZla8+69t03410Iyo9N6lV7bajMgCV6ioQlfS2E= beta=\/Eg8SA2j45sSVi28kVwBVpxT98G1w0tlenDVYuKy\/7Cn1ZZiNiwu8Z9XhGBxwrzPXrMHPEMJ omega=MEwDAgcAAgEgAiEA83r2Er9vHr5sSEcm9g\/\/rdLjOdTMtwX\/Lkbi02+24FkCIB2P804l26yketcG8WxZQJ1z4ukU0e3SqEzm4pKHzMRY ot=1 proof=MEUCIFFa+q1zdgA0OtXgdgn9gxSOMp7GBvc3vPW0YDTU2+e6AiEA8sjW3XDikxQADPoSaSw7lwL6gfXr6gwO0Hvro3RZBHU= tvd=AQAAAABaQjKEblQQgGczKfB+CSS7IY5qli8LRS9jDltkab8leo6ltwQH82VUU\/WwnpCbazVbnh4iNbcobdxv\/MTX5Y3+6xpqDgEAEa1\/SLpE\/CIg2X7GX9mtDCCvP1KdQGaT\/RKoofPSsTkACRbZcAr4DPAAAAASVGVhbVNwZWFrIFN5c3RlbXMgR21iSAAAPgFaQLsu0h3FTQax+i0qXFXX\/Bn7VcGJH8SE5AOAiuQECVvUYwlenQk= time=1514216961
[OUT] clientek ek=19doGY4WwwAeW\/zHnmFJTpnE8h9MUJZSYFNpz4aUabs= proof=MEUCIGTwtZ1E+HjDPLqlyTuaHtvWmjYW\/\/tnQgugaC5u1swtAiEA9DN+kuwxuXG80FDzKnICGQYQGZZBySQv8Nhflg\/1FwQ=
[OUT] clientinitiv alpha=3Pcn19zISkIB5g== omega=MEwDAgcAAgEgAiA5+ycSoMRRdugndbohYtH7PqS6Q6h3TV1VnGRKoZNMsQIhANn2rszHVipB13LBcY2Zf3APg7HX7ix3WWiaT5hjQrUv ot=1 ip=84.200.62.248
[ IN] initivexpand2 l=AQCBIiOUkbXLeQ\/6UhNB+8iJnwLYGZJglZoDFSTt+7awWgAJFtlwLxmo8AAAACVUZWFtU3BlYWsgU3lzdGVtcyBHbWJIAADtwskuiFg0FkafvNvS1uwz67b2lEhMnOkAygPvo0waGAAJQrh2HBxqvQAAACRUZWFtU3BlYWsgc3lzdGVtcyBHbWJIAADd85KDiA8UeqB5G9MBtNZ879CYBnfbjc\/OVj0j0xMcqQIJQ7qACi5lgAYAAAAAVGVhbVNwZWFrIFN5c3RlbXMgR21iSAAASpEEQfPJOP8aeecPLtzcu8iYmtqBJn8MWq+8lSQljYcgCV6iyAlfS4g= beta=JLFcgyWwlYNzy5lsTGJKGz6rvmShHrb6YEZfq4TXwTLSiWDGqckf6ywiMOP2MGAc1y1yQsEi omega=MEwDAgcAAgEgAiEA83r2Er9vHr5sSEcm9g\/\/rdLjOdTMtwX\/Lkbi02+24FkCIB2P804l26yketcG8WxZQJ1z4ukU0e3SqEzm4pKHzMRY ot=1 proof=MEYCIQCpKZJCmQCHyC2PLIleZVAl1fSTdnzqcNxhiXxVAHtUHgIhAPvPfziHtiqn36nB7KSVuKV+gMA29OL87bI1HP6CJNw2 tvd=AQAAAABaQjKEblQQgGczKfB+CSS7IY5qli8LRS9jDltkab8leo6ltwQH82VUU\/WwnpCbazVbnh4iNbcobdxv\/MTX5Y3+6xpqDgEAEa1\/SLpE\/CIg2X7GX9mtDCCvP1KdQGaT\/RKoofPSsTkACRbZcAr4DPAAAAASVGVhbVNwZWFrIFN5c3RlbXMgR21iSAAAPgFaQLsu0h3FTQax+i0qXFXX\/Bn7VcGJH8SE5AOAiuQECVvUYwlenQk= time=1514217000
[OUT] clientek ek=yGZb1Qp0Y\/V7T+rMwcqtzUeOTIGgE6+7gcKxAw2OMPU= proof=MEQCIHdgsGlufstf\/ab1TvvM740Azs56jyGFmo93ijr53k1FAiBHNhWkV9xLUG19jpZGGe86SgCDli7GdSrv61ZGr3jD9g==
bM5HB+Ox/Wht38dd6/VeB7L76ebcpP9YgKzWAk4lmQ8=

View File

@ -1,63 +0,0 @@
#include <iostream>
#include <src/Identity.h>
#include <sstream>
#include "HideString.h"
DEFINE_HIDDEN_STRING(HeaderMessage, 0x44, ('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')(' ')('T')('S')('3')(' ')('H')('a')('s')('h')(' ')('b')('y')(' ')('W')('o')('l')('v')('e')('r')('i')('n')('D')('E')('V')(' ')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#')('#'));
using namespace ts;
using namespace std;
inline string crypt(string in){
stringstream result;
result << "DEFINE_HIDDEN_STRING(EncryptionKey, 0xA5, ";
for(char c : in)
result << "('" << c << "')";
result << ");";
return result.str();
}
int main(int argc, char** argv) {
cout << GetHeaderMessage() << endl;
if(argc < 3) {
cerr << "Invalid arguments. ./TSHash <threads> <MaxLevel> [<BlockSize> = 1.000.000]" << endl;
return 0;
}
init_LTM();
if(register_prng(&sprng_desc) == -1) {
cerr << "could not setup prng" << endl;
return EXIT_FAILURE;
}
if (register_cipher(&rijndael_desc) == -1) {
cerr << "could not setup rijndael" << endl;
return EXIT_FAILURE;
}
int threads = atoi(argv[1]);
int level = atoi(argv[2]);
int blockSize = argc > 3 ? atoi(argv[3]) : 1 * 1000 * 1000;
cout << "# Creating new identity (Threads: " << threads << " Level: " << level << " Size: " << blockSize << ")" << endl;
auto identity = Identity::createNew();
cout << "IDENTITY: " << identity->exportIdentity() << endl;
cout << "# Start hashing" << endl;
if(!identity->improveSecurityLevelMultithreaded(level, threads, blockSize, 0, true)) {
cout << "ERROR: Could not improve identity!" << endl;
return 1;
}
cout << "INFO: Found identity!" << endl;
cout << "IDENTITY: " << identity->exportIdentity() << endl;
cout << "LEVEL: " << identity->getSecurityLevel() << endl;
return 0;
}
/*
#IDENTITY: 5513931022VPXfjXSN1qRa2IZvTpS3xs+L7YvcBI2lTfXgOWAkaAQwQVgR8BXtWJ1MKUSh/HGNGNgdVGWYHcCg1BgQie3pValZZB39hVE4HBStcAA5SUz9Tf1JbXVABBVUJUwFmFkJZLlZUfCtaZXFBaUVBZ1poOXlQd09KSzN6ejYxMjVnaGN3bmtSKzRPOXdvZWJObVpaT3gyOTA3ND0=
#LEVEL: 36
#IDENTITY: 0VdYzXyIWNlPR991zQZLQoGLDYA4JvCX9GQ3MAYzpBRABWAHZTAmJvNQUAMxEEKGQDJVlnanF1YDdQQn0GewlXVWoAQmVMLX9FVyZaMAI7KlAIeXpPKGMCJ3BTVAJHLGlUHARbBlpqSUNJUURISXY1UXJCYmlBMHlZOVV3dFdRRXovM0lkU1hzNFJvWTkwT1JienA5bVRRPT0=
Current level = 41 at 1233527956186
Current offset index: 3750576000000 block size: 1000000
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +0,0 @@
syntax = "proto2";
package ts.proto.license.teamspeak;
message LicenseData { //_ZTIN3com10teamspeak310accounting8protobuf19Signed_License_InfoE => Signed_License_Info
required bytes chain = 1;
required bytes root = 2;
required int32 slots = 3;
required int32 servers = 4;
required string type = 5;
}
message License {
required LicenseData license = 1;
required bytes sign_chain = 2;
required bytes license_sign = 3;
}

View File

@ -1,218 +0,0 @@
//
// Created by wolverindev on 07.10.17.
//
#include <iostream>
#include <openssl/sha.h>
#include "misc/base64.h"
#include "Identity.h"
#define ECC_TYPE_INDEX 5
using namespace std;
static const char *TSKEY =
"b9dfaa7bee6ac57ac7b65f1094a1c155"
"e747327bc2fe5d51c512023fe54a2802"
"01004e90ad1daaae1075d53b7d571c30"
"e063b5a62a4a017bb394833aa0983e6e";
static int obfuscateInplace(char *data, uint32_t length) {
int dataSize = min((uint32_t) 100, length);
for (int i = 0; i < dataSize; i++) {
data[i] ^= TSKEY[i];
}
char hash[20];
hash_state ctx;
if (sha1_init(&ctx) != CRYPT_OK)
{ return -1; }
if (sha1_process(&ctx, (uint8_t*)data + 20, strlen(data + 20)) != CRYPT_OK)
{ return -1; }
if (sha1_done(&ctx, (uint8_t*)hash) != CRYPT_OK)
{ return -1; }
for (int i = 0; i < 20; i++) {
data[i] ^= hash[i];
}
return 0;
}
static int deObfuscateInplace(char *data, uint32_t length) {
char hash[20];
hash_state ctx;
if (sha1_init(&ctx) != CRYPT_OK)
{ return -1; }
if (sha1_process(&ctx, (uint8_t*)data + 20, strlen(data + 20)) != CRYPT_OK)
{ return -1; }
if (sha1_done(&ctx, (uint8_t*)hash) != CRYPT_OK)
{ return -1; }
for (int i = 0; i < 20; i++) {
data[i] ^= hash[i];
}
int dataSize = min((uint32_t) 100, length);
for (int i = 0; i < dataSize; i++) {
data[i] ^= TSKEY[i];
}
return 0;
}
namespace ts {
Identity* Identity::createNew() {
auto result = new Identity();
prng_state rndState{};
memset(&rndState, 0, sizeof(prng_state));
int err;
result->keyPair = new ecc_key;
cout << " -> " << find_prng("sprng") << endl;
if((err = ecc_make_key_ex(&rndState, find_prng("sprng"), result->keyPair, &ltc_ecc_sets[ECC_TYPE_INDEX])) != CRYPT_OK) {
cerr << "Cant create a new identity (Keygen)" << endl;
cerr << "Message: " << error_to_string(err) << endl;
delete result;
return nullptr;
}
return result;
}
Identity::Identity(std::string asnStruct, int64_t keyOffset, int64_t lastCheckedOffset) {
this->keyOffset = keyOffset;
this->lastCheckedOffset = lastCheckedOffset;
importKey(asnStruct);
}
Identity::Identity(std::string data) : Identity() {
int vindex = data.find('V');
assert(vindex > 0);
auto slevel = data.substr(0, vindex);
assert(slevel.find_first_not_of("0123456789") == std::string::npos);
this->keyOffset = stol(slevel);
data = data.substr(vindex + 1);
data = base64::decode(data);
if(deObfuscateInplace((char *) data.data(), data.length()) < 0) {
cerr << "Cand decript identitry data" << endl;
return;
}
importKey(base64::decode(data));
}
Identity::Identity() {
this->keyOffset = 0;
this->lastCheckedOffset = 0;
this->keyPair = nullptr;
}
Identity::~Identity() {
delete this->keyPair;
this->keyPair = nullptr;
}
void Identity::importKey(std::string asnStruct) {
this->keyPair = new ecc_key;
int err;
if((err = ecc_import_ex((const unsigned char *) asnStruct.data(), asnStruct.length(), this->keyPair, &ltc_ecc_sets[ECC_TYPE_INDEX])) != CRYPT_OK){
delete this->keyPair;
this->keyPair = nullptr;
cerr << "Cant import identity from asn structure" << endl;
cerr << "Message: " << error_to_string(err) << endl;
return;
}
}
std::string Identity::exportIdentity() {
string data = privateKey();
obfuscateInplace((char *) data.data(), data.length());
return to_string(this->lastValidKeyOffset()) + "V" + base64_encode(data);
}
std::string Identity::publicKey() {
assert(this->keyPair);
size_t bufferLength = 1028;
char buffer[bufferLength];
ecc_export((unsigned char *) buffer, &bufferLength, PK_PUBLIC, this->keyPair);
return base64_encode(string(buffer, bufferLength));
}
std::string Identity::privateKey() {
assert(this->keyPair);
size_t bufferLength = 1028;
char buffer[bufferLength];
ecc_export((unsigned char *) buffer, &bufferLength, PK_PRIVATE, this->keyPair);
return base64_encode(string(buffer, bufferLength));
}
ecc_key& Identity::getPrivateKey() {
return *keyPair;
}
#define MaxUlongString 20
bool Identity::improveSecurityLevel(int target) {
auto publicKey = this->publicKey();
char hashBuffer[publicKey.length() + MaxUlongString];
memcpy(hashBuffer, publicKey.data(), publicKey.length());
this->lastCheckedOffset = max(this->lastCheckedOffset, this->keyOffset);
int best = getSecurityLevel(hashBuffer, publicKey.length(), this->lastCheckedOffset);
while(true){
if(best >= target) return true;
int currentLevel = getSecurityLevel(hashBuffer, publicKey.length(), this->lastCheckedOffset);
if(currentLevel >= best){
this->keyOffset = this->lastCheckedOffset;
best = currentLevel;
}
this->lastCheckedOffset++;
}
}
int Identity::getSecurityLevel() {
auto length = publicKey().length();
char hashBuffer[length + MaxUlongString];
auto publicKey = this->publicKey();
memcpy(hashBuffer, publicKey.data(), publicKey.length());
return getSecurityLevel(hashBuffer, publicKey.length(), this->keyOffset);
}
int Identity::getSecurityLevel(char *hashBuffer, size_t keyLength, int64_t offset) {
char numBuffer[MaxUlongString];
int numLen = 0;
do {
numBuffer[numLen] = '0' + (offset % 10);
offset /= 10;
numLen++;
} while(offset > 0);
for(int i = 0; i < numLen; i++)
hashBuffer[keyLength + i] = numBuffer[numLen - (i + 1)];
char shaBuffer[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *) hashBuffer, keyLength + numLen, (unsigned char *) shaBuffer);
//Leading zero bits
register int zeroBits = 0;
register int i;
for(i = 0; i < SHA_DIGEST_LENGTH; i++)
if(shaBuffer[i] == 0) zeroBits += 8;
else break;
if(i < SHA_DIGEST_LENGTH)
for(int bit = 0; bit < 8; bit++)
if((shaBuffer[i] & (1 << bit)) == 0) zeroBits++;
else break;
return zeroBits;
}
}

View File

@ -1,44 +0,0 @@
#pragma once
#include <tomcrypt.h>
#include <string>
namespace ts {
class Identity {
public:
static Identity* createNew();
explicit Identity(std::string data);
Identity(std::string asnStruct,int64_t keyOffset,int64_t lastCheckedOffset);
~Identity();
bool valid(){ return keyPair != nullptr; }
std::string publicKey();
std::string privateKey();
std::string exportIdentity();
ecc_key* getKeyPair(){
return keyPair;
}
ecc_key& getPrivateKey();
bool improveSecurityLevel(int target);
bool improveSecurityLevelMultithreaded(int target, int nthread = 4, size_t nblockSize = 1000, size_t baseOffset = 0, bool verbose = false);
int getSecurityLevel();
int64_t lastValidKeyOffset(){ return keyOffset; }
int64_t lastTestedKeyOffset(){ return lastCheckedOffset; }
private:
Identity();
int getSecurityLevel(char* hasBuffer, size_t keyLength, int64_t offset);
void importKey(std::string asn1);
ecc_key* keyPair = nullptr;
size_t keyOffset;
size_t lastCheckedOffset;
};
}

View File

@ -1,189 +0,0 @@
//
// Created by wolverindev on 14.10.17.
//
#include <iostream>
#include <openssl/sha.h>
#include <ThreadPool/Thread.h>
#include <vector>
#include <ThreadPool/Mutex.h>
#include <zconf.h>
#include "misc/base64.h"
#include "Identity.h"
#define ECC_TYPE_INDEX 5
#define USE_OPENSSL_SHA1
using namespace std::chrono;
using namespace std;
namespace ts {
inline int calculateSecutityLevel(uint8_t* hashBuffer, uint8_t* bufferToHash, int length){
register int zeroBits = 0;
register int bit;
register int i;
SHA1(bufferToHash, length, hashBuffer);
//Leading zero bits
for(i = 0; i < SHA_DIGEST_LENGTH; i++)
if(hashBuffer[i] == 0) zeroBits += 8;
else break;
if(i < SHA_DIGEST_LENGTH)
for(bit = 0; bit < 8; bit++)
if((hashBuffer[i] & (1 << bit)) == 0) zeroBits++;
else break;
return zeroBits;
}
inline void increaseNumBuffer(char* buffer, int numOffset, int* length){
int index = *length - 1;
while(true){
if(buffer[index] == '9'){
if(index - 1 < numOffset) {
buffer[index] = '1';
buffer[*length] = '0';
*length += 1;
return;
}
buffer[index--] = '0';
} else {
buffer[index] += 1;
return;
}
}
}
#define MaxUlongString 20
bool Identity::improveSecurityLevelMultithreaded(int target, int nthread, size_t nblockSize, size_t baseOffset, bool verbose) {
if(this->getSecurityLevel() >= target)
return false;
vector<threads::Thread*> threads;
auto publicKey = this->publicKey();
size_t currentBlockIndex = max(max(this->lastCheckedOffset, this->keyOffset), baseOffset);
threads::Mutex blockIndexLock;
auto activeDigging = new bool(true);
threads::Thread* thread;
for(int threadId = 0; threadId < nthread; threadId++){
thread = new threads::Thread([&](){
size_t offset = 0;
size_t endOffset = 0;
size_t bestOffset = 0;
char shaHashBuffer[SHA_DIGEST_LENGTH];
char hashBuffer[publicKey.length() + MaxUlongString];
memcpy(hashBuffer, publicKey.data(), publicKey.length());
#ifndef SLOW
//Setup some stuff
size_t pubKeyLength = publicKey.length();
#endif
while(*activeDigging){
//Get next range
blockIndexLock.lock();
offset = currentBlockIndex;
endOffset = currentBlockIndex + nblockSize;
currentBlockIndex += nblockSize;
blockIndexLock.unlock();
int bestLevel = this->getSecurityLevel(hashBuffer, publicKey.length(), this->keyOffset);
#ifdef SLOW
while(offset < endOffset){
int currentLevel = getSecurityLevel(hashBuffer, publicKey.length(), offset);
if(currentLevel >= best){
bestOffset = offset;
best = currentLevel;
}
offset++;
}
blockIndexLock.lock();
if(best > this->getSecurityLevel()){
if(verbose) cout << "Improved -> " << best << "/" << target << endl;
this->lastCheckedOffset = bestOffset;
this->keyOffset = bestOffset;
cout << "Got level: " << best << endl;
if(best >= target){
cout << "Done!" << endl;
*activeDigging = false;
}
}
blockIndexLock.unlock();
if(verbose) cout << "round done: highest -> " << best << endl;
#else
string strStartOffset = to_string(offset);
ssize_t roundsLeft = nblockSize;
auto hashBufferLength = static_cast<int>(publicKey.length() + strStartOffset.length());
memcpy(&hashBuffer[pubKeyLength], strStartOffset.c_str(), strStartOffset.length());
while(roundsLeft-- >= 0){
auto level = calculateSecutityLevel(reinterpret_cast<uint8_t *>(shaHashBuffer), reinterpret_cast<uint8_t *>(hashBuffer), hashBufferLength);
if(level > bestLevel){
{
threads::MutexLock l(blockIndexLock);
auto strOffset = string(&hashBuffer[pubKeyLength], hashBufferLength - pubKeyLength);
bestOffset = stoull(strOffset);
auto got = this->getSecurityLevel();
if(got >= level) {
cout << "Already got bedder level! (" << got << ")" << endl;
bestLevel = got;
continue;
}
if(verbose) cout << "Improved -> " << level << "/" << target << " [" << strOffset << "]" << endl;
this->lastCheckedOffset = bestOffset;
this->keyOffset = bestOffset;
bestLevel = level;
if(bestLevel >= target){
cout << "Done! (" << bestLevel << ")" << endl;
*activeDigging = false;
}
}
}
increaseNumBuffer(hashBuffer, pubKeyLength + 1, &hashBufferLength);
}
#endif
}
});
thread->name("IdentityHashDigger #" + to_string(threadId));
threads.push_back(thread);
}
if(verbose){
thread = new threads::Thread([&](){
auto lastIndex = currentBlockIndex;
while(*activeDigging){
for(int count = 0; count < 1000 && *activeDigging; count++)
usleep(1000);
blockIndexLock.lock();
cout << "Current level = " << this->getSecurityLevel() << " at " << this->keyOffset << endl;
cout << "Current offset index: " << currentBlockIndex << " block size: " << nblockSize << endl;
cout << "speed: " << (currentBlockIndex - lastIndex) / 1000 / 1000.f << " Mio. attemps/sec" << endl;
lastIndex = currentBlockIndex;
blockIndexLock.unlock();
}
});
thread->name("Status printer");
threads.push_back(thread);
}
for(auto elm : threads){
if(elm->state() == threads::ThreadState::RUNNING)
elm->join();
delete elm;
}
return true;
}
}

View File

@ -1,196 +0,0 @@
/*
*
* TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based
* on the implementation in boost::uuid::details.
*
* SHA1 Wikipedia Page: http://en.wikipedia.org/wiki/SHA-1
*
* Copyright (c) 2012-22 SAURAV MOHAPATRA <mohaps@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _TINY_SHA1_HPP_
#define _TINY_SHA1_HPP_
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <stdint.h>
namespace sha1
{
class SHA1
{
public:
typedef uint32_t digest32_t[5];
typedef uint8_t digest8_t[20];
inline static uint32_t LeftRotate(uint32_t value, size_t count) {
return (value << count) ^ (value >> (32-count));
}
SHA1(){ reset(); }
virtual ~SHA1() {}
SHA1(const SHA1& s) { *this = s; }
const SHA1& operator = (const SHA1& s) {
memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
memcpy(m_block, s.m_block, 64);
m_blockByteIndex = s.m_blockByteIndex;
m_byteCount = s.m_byteCount;
return *this;
}
SHA1& reset() {
m_digest[0] = 0x67452301;
m_digest[1] = 0xEFCDAB89;
m_digest[2] = 0x98BADCFE;
m_digest[3] = 0x10325476;
m_digest[4] = 0xC3D2E1F0;
m_blockByteIndex = 0;
m_byteCount = 0;
return *this;
}
SHA1& processByte(uint8_t octet) {
this->m_block[this->m_blockByteIndex++] = octet;
++this->m_byteCount;
if(m_blockByteIndex == 64) {
this->m_blockByteIndex = 0;
processBlock();
}
return *this;
}
SHA1& processBlock(const void* const start, const void* const end) {
const uint8_t* begin = static_cast<const uint8_t*>(start);
const uint8_t* finish = static_cast<const uint8_t*>(end);
while(begin != finish) {
processByte(*begin);
begin++;
}
return *this;
}
SHA1& processBytes(const void* const data, size_t len) {
const uint8_t* block = static_cast<const uint8_t*>(data);
processBlock(block, block + len);
return *this;
}
const uint32_t* getDigest(digest32_t digest) {
size_t bitCount = this->m_byteCount * 8;
processByte(0x80);
if (this->m_blockByteIndex > 56) {
while (m_blockByteIndex != 0) {
processByte(0);
}
while (m_blockByteIndex < 56) {
processByte(0);
}
} else {
while (m_blockByteIndex < 56) {
processByte(0);
}
}
processByte(0);
processByte(0);
processByte(0);
processByte(0);
processByte( static_cast<unsigned char>((bitCount>>24) & 0xFF));
processByte( static_cast<unsigned char>((bitCount>>16) & 0xFF));
processByte( static_cast<unsigned char>((bitCount>>8 ) & 0xFF));
processByte( static_cast<unsigned char>((bitCount) & 0xFF));
memcpy(digest, m_digest, 5 * sizeof(uint32_t));
return digest;
}
const uint8_t* getDigestBytes(digest8_t digest) {
digest32_t d32;
getDigest(d32);
size_t di = 0;
digest[di++] = ((d32[0] >> 24) & 0xFF);
digest[di++] = ((d32[0] >> 16) & 0xFF);
digest[di++] = ((d32[0] >> 8) & 0xFF);
digest[di++] = ((d32[0]) & 0xFF);
digest[di++] = ((d32[1] >> 24) & 0xFF);
digest[di++] = ((d32[1] >> 16) & 0xFF);
digest[di++] = ((d32[1] >> 8) & 0xFF);
digest[di++] = ((d32[1]) & 0xFF);
digest[di++] = ((d32[2] >> 24) & 0xFF);
digest[di++] = ((d32[2] >> 16) & 0xFF);
digest[di++] = ((d32[2] >> 8) & 0xFF);
digest[di++] = ((d32[2]) & 0xFF);
digest[di++] = ((d32[3] >> 24) & 0xFF);
digest[di++] = ((d32[3] >> 16) & 0xFF);
digest[di++] = ((d32[3] >> 8) & 0xFF);
digest[di++] = ((d32[3]) & 0xFF);
digest[di++] = ((d32[4] >> 24) & 0xFF);
digest[di++] = ((d32[4] >> 16) & 0xFF);
digest[di++] = ((d32[4] >> 8) & 0xFF);
digest[di++] = ((d32[4]) & 0xFF);
return digest;
}
protected:
void processBlock() {
uint32_t w[80];
for (size_t i = 0; i < 16; i++) {
w[i] = (m_block[i*4 + 0] << 24);
w[i] |= (m_block[i*4 + 1] << 16);
w[i] |= (m_block[i*4 + 2] << 8);
w[i] |= (m_block[i*4 + 3]);
}
for (size_t i = 16; i < 80; i++) {
w[i] = LeftRotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
}
uint32_t a = m_digest[0];
uint32_t b = m_digest[1];
uint32_t c = m_digest[2];
uint32_t d = m_digest[3];
uint32_t e = m_digest[4];
for (std::size_t i=0; i<80; ++i) {
uint32_t f = 0;
uint32_t k = 0;
if (i<20) {
f = (b & c) | (~b & d);
k = 0x5A827999;
} else if (i<40) {
f = b ^ c ^ d;
k = 0x6ED9EBA1;
} else if (i<60) {
f = (b & c) | (b & d) | (c & d);
k = 0x8F1BBCDC;
} else {
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i];
e = d;
d = c;
c = LeftRotate(b, 30);
b = a;
a = temp;
}
m_digest[0] += a;
m_digest[1] += b;
m_digest[2] += c;
m_digest[3] += d;
m_digest[4] += e;
}
private:
digest32_t m_digest;
uint8_t m_block[64];
size_t m_blockByteIndex;
size_t m_byteCount;
};
}
#endif

View File

@ -1,454 +0,0 @@
//
// Created by wolverindev on 07.10.17.
//
#include <log/LogUtils.h>
#include "Connection.h"
#include "misc/base64.h"
#include <misc/endianness.h>
#include <arpa/inet.h>
#include <poll.h>
#include <openssl/sha.h>
#include <bitset>
#include <protocol/Packet.h>
using namespace std;
using namespace ts;
using namespace ts::connection;
using namespace ts::protocol;
ServerConnection::ServerConnection() {
cryptionHandler = new CryptionHandler();
cryptionHandler->reset();
compressionHandler = new CompressionHandler();
readQueue = (buffer::SortedBufferQueue<ServerPacket> **) malloc(16 * sizeof(void*));
for(int i = 0; i < 16; i++) {
auto type = ts::protocol::PacketTypeInfo::fromid(i);
if(type != PacketTypeInfo::Undefined){
readQueue[i] = new buffer::SortedBufferQueue<ServerPacket>(ts::protocol::PacketTypeInfo::fromid(i), PacketTypeInfo::Command != type); //Ignore command low
} else {
readQueue[i] = nullptr;
}
}
}
ServerConnection::~ServerConnection() {
for(int i = 0; i < 16; i++)
if(readQueue[i])
delete readQueue[i];
free(readQueue);
this->rwThread->join();
}
static int sourcePort = 50000;
void ServerConnection::disconnect() {
//this->rwThread->cancel();
//this->handleThread->cancel();
this->connected = false;
if(this->socket) this->socket->close();
}
bool ServerConnection::connect(std::string host, std::string port, Identity *identity) {
this->clientIdentity = identity;
memset(&remoteAddress, 0, sizeof(remoteAddress));
remoteAddress.sin_family = AF_INET;
remoteAddress.sin_port = htons((uint16_t) std::stoi(port));
remoteAddress.sin_addr.s_addr = inet_addr(host.c_str());
#ifdef NoQt
/*
this->socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int allow = 1;
setsockopt(this->socketfd, SOL_SOCKET, SO_REUSEADDR, &allow, sizeof(int));
memset(&localAddress, 0, sizeof(localAddress));
localAddress.sin_family = AF_INET;
localAddress.sin_addr.s_addr = htonl (INADDR_ANY);
localAddress.sin_port = htons (sourcePort++);
::connect(this->socketfd, (const sockaddr *) &remoteHost, sizeof(this->remoteAddress));
//bind(this->socketfd, (struct sockaddr *) &localAddress, sizeof(localAddress));
*/
this->socket = new UdpSocket;
if(!this->socket->setup(&remoteAddress)){
cerr << "Invalid socket setup" << endl;
}
#else
#endif
this->rwThread = new threads::Thread(THREAD_SAVE_OPERATIONS, [&]() {
#ifndef NoQt
this->qtSocket = new QUdpSocket();
QObject::connect(qtSocket,SIGNAL(bytesWritten(qint64)),this,SLOT(bytesWritten(qint64)));
QObject::connect(this->qtSocket, SIGNAL(readyRead()), this, SLOT(attempDatagramRead()));
this->qtSocket->bind(QHostAddress::Any, 23111);
this->socketfd = qtSocket->socketDescriptor();
cout << "Sock fd: " << this->socketfd << endl;
#endif
/*
auto cthread = QThread::currentThread();
cout << "ex" << endl;
runOnThread(qtSocket->thread(), [&](){
cout << "try" << endl;
qtSocket->moveToThread(cthread);
cout << "Moved" << endl;
});
cout << "Start rw" << endl;
*/
this->rwExecutor();
});
/*
this->handleThread = new threads::Thread([&]() {
this->handleExecutor();
});
*/
return true;
}
#ifndef NoQt
void ServerConnection::bytesWritten(qint64 b) {
cout << "written " << b << endl;
}
void ServerConnection::attempDatagramRead() {
cout << "Data " << endl;
}
#endif
//this->socket->socketDescriptor()
void ServerConnection::rwExecutor() {
pollfd pollData = {this->socket->getSocketDescriptor(), POLLRDHUP | POLLIN | POLLOUT, 0};
buffer::RawBuffer readBuffer(512);
std::shared_ptr<protocol::ServerPacket> readedPacket;
while (socket->getSocketDescriptor() > 0 && this->connected) {
int rfds = poll(&pollData, 1, -1);
bool select = false;
if(rfds == 0) {
usleep(5 * 1000);;
continue;
} else if(rfds < 0) {
break;
}
if (pollData.revents & POLLRDHUP || pollData.revents & POLLHUP) {
select = 1;
cerr << "Connection hang up!" << endl;
return;
}
if (pollData.revents & POLLIN) {
select = 1;
ssize_t readedBytes = -1;
#ifdef NoQt
readedBytes = socket->read(readBuffer.buffer, readBuffer.length);
#ifdef DEBUG
cout << "Read bytes (" << readedBytes << ")" << endl;
#endif
#else
QHostAddress senderAddr;
quint16 senderPort;
readedBytes = this->qtSocket->readDatagram(readBuffer.buffer, readBuffer.length, &senderAddr, &senderPort);
#endif
if (readedBytes < 0) {
cout << "fatal read error: " << errno << "/" << strerror(errno) << endl;
return;
}
readedPacket = std::make_shared<ServerPacket>(pipes::buffer_view(readBuffer.buffer, readedBytes));
if(!preProgressPacket(readedPacket)){
cerr << "Invalid packet preprocess!" << endl;
readedPacket = nullptr;
goto exitRead;
}
if(readedPacket->type().type() < 0 || readedPacket->type().type() > 16){
cerr << "Invalid packet id!" << endl;
readedPacket = nullptr;
goto exitRead;
}
//Deserelize packet
this->bufferQueueLock.lock();
if(!this->readQueue[readedPacket->type().type()]->push_pack(readedPacket)){
//TODO error handling
cout << "pkId: " << be2le16((char*) readedPacket->data().data_ptr()) << " -> " << readedPacket->type().name() << endl;
}
this->bufferQueueLock.unlock();
while(this->handleNextPacket());
exitRead:;
}
if (pollData.revents & POLLOUT) {
this->bufferQueueLock.lock();
if (!this->writeQueue.empty()) {
select = 1;
buffer::RawBuffer buffer = this->writeQueue.front();
#ifdef NoQt
auto res = this->socket->write(buffer.buffer, buffer.length);
if (res == -1) {
cout << "having write error: " << errno << "/" << strerror(errno) << " -> " << buffer.length << endl;
}
//cout << string() + "Write: " + PacketType::fromid(buffer.type()).name() << endl;
#else
this->qtSocket->writeDatagram(buffer.buffer, buffer.length, QHostAddress("localhost"), htons(this->remoteAddress.sin_port));
#endif
/*
if(!PacketTypeInfo::fromid(buffer.type()).requireAcknowledge()){ //Than we need a ack!
//Wait for acknowlage
this->acknowlageQueueLock.lock();
this->acknowlageQueue.push_back(buffer);
this->acknowlageQueueLock.unlock();
}
*/
this->writeQueue.pop_front();
}
this->bufferQueueLock.unlock();
}
if (!select) {
usleep(5 * 10000);
continue;
}
}
cerr << "rw loop broken!" << endl;
}
bool ServerConnection::preProgressPacket(std::shared_ptr<protocol::ServerPacket> packet){
packet->setEncrypted(!packet->hasFlag(PacketFlag::Unencrypted));
packet->setCompressed(packet->hasFlag(PacketFlag::Compressed));
packet->setFragmentedEntry(packet->hasFlag(PacketFlag::Fragmented));
if(packet->type() == PacketTypeInfo::Init1){
}
if (packet->isEncrypted()) {
string error = "success";
if (!cryptionHandler->progressPacketIn(packet.get(), error, false)) {
cerr << "Cant decript packet! Message: " << error << endl;
cerr << "Dropping it!" << endl;
return false;
}
}
#ifdef DEBUG
cout << "[IN] Packet type -> " << packet->type().name() << " flags " << packet->flags() << " Length: " << packet->data().length() << endl;
#endif
if(packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow){ //needs an acknowledge
sendAcknowledge(packet->packetId(), packet->type() == PacketTypeInfo::CommandLow);
}
return true;
}
//TODO right packet recive order!
void ServerConnection::handleExecutor() {
shared_ptr<protocol::ServerPacket> packet = nullptr;
string error = "success";
while(this->connected){
while(this->handleNextPacket());
usleep(10 * 1000);
}
}
bool ServerConnection::handleNextPacket() {
shared_ptr<protocol::ServerPacket> packet = nullptr;
string error = "success";
if(this->autoHandle){
handleQueueLock.lock();
if(!this->handleQueue.empty()) {
packet = this->handleQueue.front();
this->handleQueue.pop_front();
}
handleQueueLock.unlock();
if(packet){
if(packet->type() == PacketTypeInfo::Ack || packet->type() == PacketTypeInfo::AckLow){
handlePacketAck(packet);
} else if(packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow){
handlePacketCommand(packet);
} else if(packet->type() == PacketTypeInfo::Ping || packet->type() == PacketTypeInfo::Pong){
handlePacketPing(packet);
} else if(packet->type() == PacketTypeInfo::Voice || packet->type() == PacketTypeInfo::VoiceWhisper){
handlePacketVoice(packet);
}
return true;
}
}
for(int index = 0; index < 16; index++){
if(this->readQueue[index]) {
if(this->readQueue[index]->available() > 0){
auto npacket = this->readQueue[index]->peekNext(0);
packet = make_shared<ServerPacket>(npacket->buffer());
packet->setEncrypted(npacket->isEncrypted());
packet->setCompressed(npacket->isCompressed());
packet->setFragmentedEntry(npacket->isFragmentEntry());
break;
}
}
}
if(!packet) return false;
if(packet->isFragmentEntry()){
packet->setFragmentedEntry(false);
int deltaPacketIndex = 0;
while(this->connected){
std::shared_ptr<protocol::ServerPacket> nextElm = this->readQueue[packet->type().type()]->peekNext(++deltaPacketIndex);
if(!nextElm)
return false;
if(!nextElm) {
cerr << "Dropped fragment?" << endl;
packet = nullptr;
break;
}
packet->append_data({nextElm->data()});
if(nextElm->hasFlag(protocol::PacketFlag::Fragmented)) break; //Tail end
nextElm = nullptr;
}
this->readQueue[packet->type().type()]->pop_packets(deltaPacketIndex);
}
this->readQueue[packet->type().type()]->pop_packets(1);
if(packet->type() != PacketTypeInfo::Init1 && !this->compressionHandler->progressPacketIn(packet.get(), error)){
cerr << "Cant decompress packet! (" << error << ")" << endl;
packet = nullptr;
return true;
}
#if defined(DEBUG_PACKET_LOG)
cout << "Parsed packet " << packet->type().name() << " with id " << packet->packetId() << ". Data:" << endl;
hexDump((void *) packet->data().data_ptr(), packet->data().length(), 16, 8, [](std::string line) {
cout << "[IN] " << line << endl;
});
#endif
handleQueueLock.lock();
this->handleQueue.push_back(packet);
handleQueueLock.unlock();
return true;
}
using namespace std::chrono;
std::shared_ptr<protocol::ServerPacket> ServerConnection::readNextPacket(bool block) {
auto start = system_clock::now();
attempGet:
if(system_clock::now() - start > seconds(5)) return nullptr;
this->handleQueueLock.lock();
if (this->handleQueue.empty()) {
this->handleQueueLock.unlock();
if (!block) return nullptr;
usleep(5 * 1000);
goto attempGet;
}
std::shared_ptr<protocol::ServerPacket> packet = std::move(this->handleQueue.front());
this->handleQueue.pop_front();
this->handleQueueLock.unlock();
return packet;
}
bool ServerConnection::setupSharedSecret(std::string alpha, std::string beta, std::string sharedKey, std::string &error) {
return this->cryptionHandler->setupSharedSecret(alpha, beta, sharedKey, error);
}
//Packet splitting not working correctly! (On clientinit dosnt wait for the second)
void ServerConnection::sendPacket(ts::protocol::ClientPacket &packet) {
int maxDataLength = 500 - packet.header().length();
if(packet.data().length() > maxDataLength){
string error;
/*
packet.enableFlag(PacketFlag::Compressed);
if(!this->compressionHandler->progressPacketOut(&packet, error)){
cerr << "Compress error!" << endl;
return;
}
packet.enableFlag(PacketFlag::Compressed);
*/
if(packet.data().length() > maxDataLength){
std::vector<shared_ptr<ClientPacket>> siblings;
siblings.reserve(8);
{ //Split packets
auto buffer = packet.data();
const auto max_length = packet.type().max_length();
while(buffer.length() > max_length * 2) {
siblings.push_back(make_shared<ClientPacket>(packet.type(), buffer.view(0, max_length)));
buffer = buffer.range(max_length);
}
if(buffer.length() > max_length) { //Divide rest by 2
siblings.push_back(make_shared<ClientPacket>(packet.type(), buffer.view(0, buffer.length() / 2)));
buffer = buffer.range(buffer.length() / 2);
}
siblings.push_back(make_shared<ClientPacket>(packet.type(), buffer));
for(const auto& frag : siblings) {
frag->setFragmentedEntry(true);
frag->enableFlag(PacketFlag::NewProtocol);
}
}
for(const auto& entry : siblings)
this->sendPacket(*entry);
return;
}
}
if(!packet.memory_state.id_branded)
packet.applyPacketId(idManager);
packet.clientId(this->clientId);
string error = "success";
if (!this->cryptionHandler->progressPacketOut(&packet, error, false)) {
cerr << "Invalid crypt -> " << error << endl;
return;
}
buffer::RawBuffer buffer(packet.buffer().length());
memcpy(&buffer.buffer[0], packet.buffer().data_ptr(), packet.buffer().length());
this->bufferQueueLock.lock();
this->writeQueue.push_back(buffer);
#if defined(DEBUG_PACKET_LOG)
cout << "Send packet " << packet.type().name() << " fragmented -> " << packet.isFragmentEntry() << " length " << packet.data().length() << " flags " << packet.flags() << " ID: " << packet.packetId() << endl;
hexDump(buffer.buffer, buffer.length, buffer.length, buffer.length);
#endif
this->bufferQueueLock.unlock();
}
void ServerConnection::sendCommand(ts::Command command, bool low) {
auto data = command.build();
protocol::ClientPacket pkt(low ? protocol::PacketTypeInfo::CommandLow : protocol::PacketTypeInfo::Command, pipes::buffer_view{(void*) data.data(), data.length()});
#ifdef DEBUG
cout << "[Client -> Server][" << pkt.type().name() << "] " << pkt.data() << endl;
#endif
if(!low) pkt.enableFlag(PacketFlag::NewProtocol);
sendPacket(pkt);
}
void ServerConnection::sendAcknowledge(uint16_t packetId, bool low) {
if(breakAck) return;
char buffer[2];
le2be16(packetId, buffer);
protocol::ClientPacket pkt(low ? protocol::PacketTypeInfo::AckLow : protocol::PacketTypeInfo::Ack, pipes::buffer_view(buffer, 2));
#ifdef DEBUG
cout << "Sending packet acknowledge for " << packetId << " (Encrypt: " << encriptAck << ")" << endl;
#endif
if(!encriptAck)
pkt.enableFlag(PacketFlag::Unencrypted);
if(!low) pkt.toggle(protocol::PacketFlag::NewProtocol, true);
sendPacket(pkt);
}

View File

@ -1,139 +0,0 @@
#pragma once
#include <ThreadPool/Thread.h>
#include <ThreadPool/Mutex.h>
#include <string>
#include <thread>
#include <netinet/in.h>
#include <deque>
#include <list>
#include <protocol/Packet.h>
#include <protocol/buffers.h>
#include <src/protocol/socket/FilteredUDPSocket.h>
#include <src/Identity.h>
#include <protocol/CryptionHandler.h>
#include <protocol/CompressionHandler.h>
#define NoQt
#ifndef NoQt
#include <QUdpSocket>
#endif
#define DEBUG_PACKET_LOG
//#define LOG_CMD
namespace ts {
namespace connection {
namespace ConnectionState {
enum ConnectionState {
UNCONNECTED,
LLHANDSCHAKE,
HANDSCHAKE,
CONNECTED,
DISCONNECTED
};
}
class ServerConnection
#ifndef NoQt
: public QObject {
Q_OBJECT
#else
{
#endif
public:
ServerConnection();
~ServerConnection();
bool connect(std::string host, std::string port, Identity* identity);
void disconnect();
ConnectionState::ConnectionState getConnectionState(){ return cstate; }
bool handshake(std::string &errorMessage);
bool handshakeNew(Command &cmd, const std::string& alpha, std::string &errorMessage);
void sendPacket(ts::protocol::ClientPacket& packet);
void sendCommand(ts::Command command, bool low = false);
void sendAcknowledge(uint16_t packetId, bool low = false);
std::shared_ptr<protocol::ServerPacket> readNextPacket(bool block = true);
uint16_t getClientId(){
return this->clientId;
}
void setClientId(uint16_t id){
this->clientId = id;
}
#ifndef NoQt
public slots:
void attempDatagramRead();
void bytesWritten(qint64);
#endif
private:
bool encriptAck = false;
bool preProgressPacket(std::shared_ptr<protocol::ServerPacket> packet);
void rwExecutor();
void handleExecutor();
bool handleNextPacket();
bool setupSharedSecret(std::string alpha, std::string beta, std::string sharedKey, std::string& error);
void handlePacketPing(std::shared_ptr<protocol::ServerPacket> packet);
void handlePacketCommand(std::shared_ptr<protocol::ServerPacket> packet);
void handlePacketAck(std::shared_ptr<protocol::ServerPacket> packet);
void handlePacketVoice(std::shared_ptr<protocol::ServerPacket> packet);
bool connected = true;
sockaddr_in remoteAddress;
sockaddr_in localAddress;
UdpSocket* socket;
threads::Thread* rwThread = nullptr;
std::deque<buffer::RawBuffer> writeQueue;
#ifndef NoQt
QUdpSocket* qtSocket = nullptr;
#endif
threads::Mutex bufferQueueLock;
buffer::SortedBufferQueue<protocol::ServerPacket>** readQueue = nullptr;
//std::deque<RawBuffer> readQueue;
std::deque<buffer::RawBuffer> acknowlageQueue;
threads::Mutex acknowlageQueueLock;
protocol::PacketIdManager idManager;
threads::Thread* handleThread = nullptr;
std::list<std::shared_ptr<protocol::ServerPacket>> handleQueue; //Parsed packets
threads::Mutex handleQueueLock;
bool autoHandle = false;
ts::connection::CryptionHandler* cryptionHandler = nullptr;
ts::connection::CompressionHandler* compressionHandler = nullptr;
std::string remoteHost;
uint16_t remotePort;
Identity* clientIdentity;
ConnectionState::ConnectionState cstate = ConnectionState::UNCONNECTED;
bool breakAck = false;
/**
* TS3 Client data
*/
uint16_t clientId = 0;
std::deque<ChannelId> channels;
};
}
}

View File

@ -1,361 +0,0 @@
//
// Created by wolverindev on 08.10.17.
//
#include <tommath.h>
#include <bitset>
#include <openssl/sha.h>
#include "Connection.h"
#include "misc/base64.h"
#include "misc/endianness.h"
using namespace std;
using namespace std::chrono;
using namespace ts;
using namespace ts::connection;
using namespace ts::protocol;
const int InitVersionLength = 4;
const uint8_t InitVersion[InitVersionLength] = {0x09, 0x83, 0x8C, 0xCF};
/**
* Maybe memset to 0 for security?
*/
#define RESET_DATA \
bufferIndex = 0; \
delete pkt; \
pkt = nullptr;
inline ClientPacket *solvePuzzle(shared_ptr<ServerPacket> response, Identity *, std::string &);
inline std::string toString(mp_int* num){
char buffer[2048];
memset(buffer, 0, 2048);
auto len = mp_todecimal(num, buffer);
return string(buffer);
}
extern void hexdump(std::ostream& outs, const std::string& s, size_t line_len = 16);
bool ServerConnection::handshake(std::string &errorMessage) {
//setup the init mac
/**
* Low level
*/
ts::protocol::ClientPacket *pkt;
shared_ptr<ServerPacket> response;
int maxBufferSize = 512;
size_t bufferIndex = 0;
uint8_t buffer[maxBufferSize];
memset(buffer, 0, maxBufferSize);
int err = 0;
string error = "success";
beginCoocie:
memcpy(buffer, InitVersion, InitVersionLength);
bufferIndex += InitVersionLength;
buffer[bufferIndex++] = 0x00; //Login state
auto millis = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
memcpy(&buffer[bufferIndex], &millis, 4);
bufferIndex += 4;
//generate the alpha key
for (int i = 0; i < 4; i++) buffer[bufferIndex++] = (uint8_t) std::rand();
bufferIndex += 8; //Reserved bytes
pkt = new ts::protocol::ClientPacket(ts::protocol::PacketTypeInfo::Init1, pipes::buffer_view((void *) buffer, bufferIndex));
pkt->clientId(0);
pkt->toggle(ts::protocol::PacketFlag::Unencrypted, true);
pkt->applyPacketId(101, 0);
this->sendPacket(*pkt);
RESET_DATA;
response = readNextPacket();
if (!response) {
errorMessage = "could not get a valid response!";
return false;
}
if (response->type() != protocol::PacketTypeInfo::Init1) {
errorMessage = "invalid response type. Got: " + response->type().name();
return false;
}
if (response->data()[0] != 1) {
errorMessage = "iInvalid requested login type (" + to_string((int) response->data()[0]) + " == 1)";
return false;
}
//the second request of the manager
memcpy(buffer, InitVersion, InitVersionLength);
bufferIndex += InitVersionLength;
buffer[bufferIndex++] = 0x02; //Login state
if(response)
memcpy(&buffer[bufferIndex], response->data().string().substr(1, 16).data(), 16);
bufferIndex += 16; //Servers 16 bytes
if(response)
memcpy(&buffer[bufferIndex], response->data().string().substr(17, 4).data(), 4);
bufferIndex += 4; //My own 16 bytes, reversed
pkt = new ts::protocol::ClientPacket(ts::protocol::PacketTypeInfo::Init1, pipes::buffer_view((void *) buffer, bufferIndex));
pkt->clientId(0);
pkt->toggle(ts::protocol::PacketFlag::Unencrypted, true);
pkt->applyPacketId(101, 0);
this->sendPacket(*pkt);
RESET_DATA;
//We got the RSA challenge
response = readNextPacket();
if (!response) {
errorMessage = "could not get a valid response!";
return false;
}
if (response->type() != protocol::PacketTypeInfo::Init1) {
errorMessage = "invalid response type";
return false;
}
if (response->data()[0] != 3) {
if(response->data()[0] == 127) {
cout << "COOCIE RESET!" << endl;
goto beginCoocie;
}
hexdump(cout, response->data().string());
errorMessage = "Invalid requested login type (" + to_string((int) response->data()[0]) + " == 3 | unencripted -> " + (response->hasFlag(PacketFlag::Unencrypted) ? "true" : "false") + ")";
return false;
}
//Generate puzzel response
std::string alpha;
pkt = solvePuzzle(response, this->clientIdentity, alpha);
pkt->applyPacketId(101, 0);
this->sendPacket(*pkt);
RESET_DATA;
cout << "manager init done" << endl;
this->encriptAck = true;
response = readNextPacket();
if (!response) {
errorMessage = "could not get a valid response!";
return false;
}
if (response->type() != protocol::PacketTypeInfo::Command) {
errorMessage = "invalid response type: " + response->type().name();
return false;
}
auto command = response->asCommand();
if (command.getCommand().compare("initivexpand") != 0) {
// errorMessage = "invalid response command. Got: " + command.getCommand() + " Expected: initivexpand";
return this->handshakeNew(command, alpha, errorMessage);
}
//std::string alpha = base64::decode(command[0]["alpha"]);
std::string beta = base64::decode(command[0]["beta"]);
std::string omega = base64::decode(command[0]["omega"]); //Remotes public key
cout << "RESPONSE! -> " << command.build() << endl;
//Read public key
ecc_key remotePublicKey{};
if ((err = ecc_import((const unsigned char *) omega.data(), omega.length(), &remotePublicKey)) != CRYPT_OK) {
errorMessage = "ecc_import(...) returned " + to_string(err) + "/" + error_to_string(err);
return false;
}
if(strcmp(remotePublicKey.dp->name, "ECC-256") != 0){
errorMessage = "invalid imported public key! Curve found " + string(remotePublicKey.dp->name);
return false;
}
size_t sharedSecretLength = 32;
char sharedSecret[sharedSecretLength];
if ((err = ecc_shared_secret(clientIdentity->getKeyPair(), &remotePublicKey, (unsigned char *) sharedSecret, &sharedSecretLength)) != CRYPT_OK) {
errorMessage = "ecc_shared_secret(...) returned " + to_string(err) + "/" + error_to_string(err);
return false;
}
if (!setupSharedSecret(alpha, beta, string(sharedSecret, sharedSecretLength), error)) {
errorMessage = "setupSharedSecret(...) failed: " + error;
return false;
}
//this->readQueue[PacketType::Command.type()]->reset();
//TS 3.1
/*
response = readNextPacket();
if (!response) {
errorMessage = "could not get a valid response!";
return false;
}
if (response->type() != protocol::PacketType::Command) {
errorMessage = "invalid response type: " + response->type().name();
return false;
}
command = response->asCommand();
cout << "Having initiv2 -> " << response->data() << endl;
*/
this->idManager.nextPacketId(PacketTypeInfo::Command);
Command clientinit("clientinit");
//94ec66de-5940-4e38-b002-970df0cf6c94,62444179-0d99-42ba-a45c-c6b1557d079a,d95f9901-c42d-4bac-8849-7164fd9e2310
//clientinit["client_badges"] = "badges=450f81c1-ab41-4211-a338-222fa94ed157,c9e97536-5a2d-4c8e-a135-af404587a472,94ec66de-5940-4e38-b002-970df0cf6c94"; //,62444179-0d99-42ba-a45c-c6b1557d079a
clientinit["client_nickname"] = "Wolf C++ XXXX";
clientinit["client_version"] = "3.1 [Build: 1471417187]";
clientinit["client_platform"] = "Windows";
clientinit["client_version_sign"] = "Vr9F7kbVorcrkV5b/Iw+feH9qmDGvfsW8tpa737zhc1fDpK5uaEo6M5l2DzgaGqqOr3GKl5A7PF9Sj6eTM26Aw==";
clientinit["client_input_hardware"] = true;
clientinit["client_output_hardware"] = true;
clientinit["client_default_channel"] = "";
clientinit["client_default_channel_password"] = "";
string password;
if(!password.empty()){
char passwordBuffer[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *) password.data(), password.length(), (unsigned char *) passwordBuffer);
password = base64_encode(string(passwordBuffer, SHA_DIGEST_LENGTH));
}
clientinit["client_server_password"] = password;
clientinit["client_meta_data"] = "";
clientinit["client_key_offset"] = this->clientIdentity->lastValidKeyOffset();
clientinit["client_nickname_phonetic"] = "";
clientinit["client_default_token"] = "";
clientinit["hwid"] = "123,456123123123";
sendCommand(clientinit);
while(true){
response = readNextPacket();
if (!response) {
errorMessage = "could not get a valid response!";
return false;
}
if(response->type() == PacketTypeInfo::Ack) continue;
break;
}
//TODO check ack id
if (!response) {
errorMessage = "could not get a valid response!";
return false;
}
if (response->type() != protocol::PacketTypeInfo::Command) {
errorMessage = "invalid response type: " + response->type().name();
return false;
}
if(response->asCommand().getCommand() == "initserver"){ //Got success
this->handleQueueLock.lock();
this->handleQueue.push_front(response);
this->handleQueueLock.unlock();
this->setClientId(response->asCommand()["aclid"]);
this->autoHandle = true;
cout << "Successfull connected!" << endl;
/*
std::thread([&](){
usleep(1000 * 1000);
cout << " -> send extra command" << endl;
//this->sendCommand(Command("channelsubscribeall return_code=1:i"));
while(true){
//this->sendCommand(Command("getconnectioninfo clid=320 return_code=1:112"));
//this->sendCommand(Command("ftgetfilelist cid=0 cpw path=\\/icons return_code=1:z0"));
this->sendCommand(Command("servergrouppermlist sgid=6 return_code=1:112"));
usleep(10 * 1000 * 1000);
}
//Command cmd("channelgetdescription cid=1 return_code=1:3o");
//Command cmd("clientupdate client_nickname=WolverinDEV22 return_code=__1_");
//Command cmd("clientdisconnect reasonid=8 reasonmsg=leaving");
//this->sendCommand(Command("permissionlist return_code=__1_"));
//this->sendCommand(Command("clientgetvariables clid=" + to_string(this->clientId)));
}).detach();
*/
return true;
}
cout << "Invalid connect: " << response->data() << endl;
//TODO error handling
return true;
}
inline ClientPacket* solvePuzzle(shared_ptr<ServerPacket> response, Identity *identity, std::string &alpha) {
uint32_t puzzelLength = be2le32(&((char*) response->data().data_ptr())[1 + 128]); //1 for the first byte (the state byte)
auto buffer = (char*) response->data().data_ptr();
char alphaBuffer[10];
for (int index = 0; index < 10; index++)
alphaBuffer[index] = 0; //rand();
alpha = string(alphaBuffer, 10);
//Generating command
auto pkey = identity->publicKey();
ts::Command command("clientinitiv", {
{"alpha", base64_encode(alphaBuffer, 10)},
{"omega", pkey},
{"ip", ""},
{"ot", 1} //Required by 3.1
});
std::string cmd = command.build();
//Sloving puzzel
mp_int x{};
mp_int n{};
mp_int result{};
//mp_init_multi(&x, &n, &result);
mp_init(&x);
mp_init(&n);
mp_init(&result);
char numBuffer[2048];
mp_read_unsigned_bin(&x, (const unsigned char *) &response->data()[1], 64); //One offset
mp_read_unsigned_bin(&n, (const unsigned char *) &response->data()[1 + 64], 64); //1 + 64 offset
cout << "X: " << toString(&x) << endl;
cout << "N: " << toString(&n) << endl;
cout << "Length: " << puzzelLength << endl;
mp_int exp{};
mp_init(&exp);
mp_2expt(&exp, puzzelLength);
//x ** (2 ** puzzelLength) mod n
int err = 0;
if ((err = mp_exptmod(&x, &exp, &n, &result)) != CRYPT_OK) {
cerr << "Invalid crypt: " << err << "/" << error_to_string(err) << endl;
}
int resultBufferLength = mp_unsigned_bin_size(&result);
char resultBuffer[resultBufferLength];
mp_to_unsigned_bin(&result, (unsigned char *) resultBuffer);
//mp_clear_multi(&x, &n, &exp, &result);
mp_clear(&x);
mp_clear(&n);
mp_clear(&exp);
mp_clear(&result);
size_t packetBufferLength = InitVersionLength + 1 + 232 + 64 + cmd.length();
char packetBuffer[packetBufferLength];
memset(packetBuffer, 0, packetBufferLength);
memcpy(packetBuffer, InitVersion, InitVersionLength);
packetBuffer[InitVersionLength] = 0x04;
//Copy old data
memcpy(&packetBuffer[InitVersionLength + 1], &response->data()[1], 232);
memcpy(&packetBuffer[InitVersionLength + 1 + 232 + (64 - resultBufferLength)], resultBuffer, resultBufferLength);
memcpy(&packetBuffer[InitVersionLength + 1 + 232 + 64], cmd.data(), cmd.length());
cout << "sending puzzel sulution" << endl;
auto pkt = new ts::protocol::ClientPacket(ts::protocol::PacketTypeInfo::Init1, pipes::buffer_view((void *) packetBuffer, packetBufferLength));
pkt->clientId(0);
pkt->toggle(ts::protocol::PacketFlag::Unencrypted, true);
return pkt;
}

View File

@ -1,158 +0,0 @@
#include <protocol/Packet.h>
#include <arpa/inet.h>
#include "Connection.h"
#include "misc/base64.h"
#include "misc/endianness.h"
using namespace std;
using namespace ts;
using namespace ts::connection;
using namespace ts::protocol;
//notifystatusfiletransfer clientftfid=4093 status=2063 msg=lost\sfile\stransfer\sconnection size=16384
extern void hexdump(std::ostream& outs, const std::string& s, size_t line_len = 16);
inline void downloadStuff(std::string key, uint16_t port, uint64_t size){
threads::Thread([key, port, size](){
int socketId = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
assert(socketId > 1);
sockaddr_in server;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( port );
//Connect to remote server
if (connect(socketId , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
return;
}
uint32_t readed = 0;
assert(send(socketId, key.data(), key.length(), 0) > 0);
while(readed < size + 3){
char buffer[size];
auto readedBytes = recv(socketId, buffer, size - readed, MSG_DONTWAIT);
if(readedBytes < 0) {
//cerr << "Invalid ft read" << endl;
continue;
}
if(readedBytes == 0){
continue;
}
hexdump(cout, string(buffer, readedBytes));
readed += readedBytes;
}
cout << "File downloaded!" << endl;
}).detach();
}
void ServerConnection::handlePacketAck(std::shared_ptr<protocol::ServerPacket> packet) {
auto packetId = be2le16((const char*) packet->data().data_ptr());
#if defined(DEBUG_PACKET_LOG) || defined(LOG_ACK)
cout << "Got ack for " << packetId << endl;
#endif
}
void ServerConnection::handlePacketCommand(std::shared_ptr<protocol::ServerPacket> packet) {
auto command = packet->asCommand();
#if defined(DEBUG_PACKET_LOG) || defined(LOG_CMD)
cout << "[Server -> Client][" << packet->type().name() << "] " << packet->data() << endl;
#endif
if (command.getCommand().compare("notifyconnectioninforequest") == 0) { //TODO
cout << "Send response" << endl;
Command cmd(
string("setconnectioninfo"), {
{"connection_ping", 10000000},
{"connection_ping_deviation", 10000000},
{"connection_packets_sent_speech", 0},
{"connection_packets_sent_keepalive", 0},
{"connection_packets_sent_control", rand()},
{"connection_bytes_sent_speech", 0},
{"connection_bytes_sent_keepalive", 0},
{"connection_bytes_sent_control", 0},
{"connection_packets_received_speech", 0},
{"connection_packets_received_keepalive", 0},
{"connection_packets_received_control", 0},
{"connection_bytes_received_speech", 0},
{"connection_bytes_received_keepalive", 0},
{"connection_bytes_received_control", 0},
{"connection_server2client_packetloss_speech", 10000000},
{"connection_server2client_packetloss_keepalive", 10000000},
{"connection_server2client_packetloss_control", 10000000},
{"connection_server2client_packetloss_total", 10000000},
{"connection_bandwidth_sent_last_second_speech", 0},
{"connection_bandwidth_sent_last_second_keepalive", 0},
{"connection_bandwidth_sent_last_second_control", 0},
{"connection_bandwidth_sent_last_minute_speech", 0},
{"connection_bandwidth_sent_last_minute_keepalive", 0},
{"connection_bandwidth_sent_last_minute_control", 0},
{"connection_bandwidth_received_last_second_speech", 0},
{"connection_bandwidth_received_last_second_keepalive", 0},
{"connection_bandwidth_received_last_second_control", 0},
{"connection_bandwidth_received_last_minute_speech", 0},
{"connection_bandwidth_received_last_minute_keepalive", 0},
{"connection_bandwidth_received_last_minute_control", 0}
}
);
sendCommand(cmd, true);
} else if (command.command() == "notifyserverupdated") {
#if defined(DEBUG_PACKET_LOG) || defined(LOG_CMD)
cout << "notifyserverupdated -> " << endl;
cout << "Last data: " << packet->data().string().substr(packet->data().length() - 10) << endl;
#endif
} else if (command.command() == "notifystartdownload") {
cout << "Client download: " << command.build() << endl;
auto port = command["port"].as<uint16_t>();
auto key = command["ftkey"].string();
auto size = command["size"].as<uint64_t>();
downloadStuff(key, port, size);
} else if (command.command() == "channellist") {
cout << "Breaking ack" << endl;
for (int index = 0; index < command.bulkCount(); index++) {
this->channels.push_back(command[index]["cid"].as<ChannelId>());
}
}
}
void ServerConnection::handlePacketVoice(std::shared_ptr<protocol::ServerPacket> packet) {}
static int pingIndex = 0;
void ServerConnection::handlePacketPing(std::shared_ptr<protocol::ServerPacket> packet) {
if(packet->type() == PacketTypeInfo::Pong){
//cout << "[PING] gota " << be2le16(packet->data().data()) << endl;
return;
}
char buffer[2];
le2be16(packet->packetId(), buffer);
ClientPacket pkt(PacketTypeInfo::Pong, pipes::buffer_view{buffer, 2});
pkt.enableFlag(PacketFlag::Unencrypted);
sendPacket(pkt);
ClientPacket ping(PacketTypeInfo::Ping, pipes::buffer_view{buffer, 0});
ping.enableFlag(PacketFlag::Unencrypted);
sendPacket(ping);
//cout << "[PING] Reqe " << ping.packetId() << endl;
//cout << "[PONG] Send " << packet->packetId() << endl;
if(this->clientId > 0 && this->channels.size() > 0) {
Command command("clientmove");
command["clid"] = this->clientId;
auto idx = rand() % this->channels.size();
command["cid"] = this->channels[idx];
this->sendCommand(command);
std::thread([&] {
threads::self::sleep_for(chrono::seconds(1));
Command cmd("channelcreate");
cmd["channel_name"] = to_string(rand()) + "_" + to_string(rand());
//this->sendCommand(cmd);
}).detach();
}
}

View File

@ -1,154 +0,0 @@
#include <ed25519/ed25519.h>
#include <ed25519/sha512.h>
#include <misc/base64.h>
#include <misc/digest.h>
#include "Connection.h"
#include "License.h"
#include <log/LogUtils.h>
using namespace std;
using namespace std::chrono;
using namespace ts;
using namespace license::teamspeak;
using namespace ts::connection;
using namespace ts::protocol;
int __ed_sha512_init(sha512_context* ctx) {
//assert(!ctx->context);
ctx->context = new hash_state{};
return sha512_init((hash_state*) ctx->context) == CRYPT_OK;
}
int __ed_sha512_final(sha512_context* ctx, unsigned char *out) {
assert(ctx->context);
auto result = sha512_done((hash_state*) ctx->context, out) == CRYPT_OK;
delete (hash_state*) ctx->context;
return result;
}
int __ed_sha512_update(sha512_context* ctx, const unsigned char *msg, size_t len) {
assert(ctx->context);
return sha512_process((hash_state*) ctx->context, msg, len) == CRYPT_OK;
}
static sha512_functions __ed_sha512_functions {
__ed_sha512_init,
__ed_sha512_final,
__ed_sha512_update
};
bool ServerConnection::handshakeNew(Command &initivexpand2, const std::string& alpha, std::string &errorMessage) {
if(&__ed_sha512_functions != &_ed_sha512_functions)
_ed_sha512_functions = __ed_sha512_functions;
cout << initivexpand2.build() << endl;
u_char seed[32 * 2];
u_char clientPrivateKey[32];
u_char clientPublicKey[32];
ed25519_create_keypair(clientPublicKey, clientPrivateKey, seed);
cout << "Client key: " << base64::encode((char*) clientPrivateKey, 32) << endl;
cout << "Privet key:" << endl;
hexDump(clientPrivateKey, 32);
cout << "Public key:" << endl;
hexDump(clientPublicKey, 32);
auto license = base64::decode(initivexpand2["l"]);
auto licensestream = stringstream(license);
auto chain = LicenseChain::parse(licensestream, errorMessage);
if(!chain) return false;
chain->print();
unique_ptr<ecc_key> serverPublic(new ecc_key{});
auto omega = base64::decode(initivexpand2["omega"]);
ecc_import((u_char*) omega.data(), omega.length(), serverPublic.get());
//7B 1E AC 02 CE 77 35 0E EF C4 5C 1C F7 54 04 87 A9 A7 64 A7 8F 04 F7 53 58 64 84 D7 0A 97 F2 63
//[0x7b, 0x1e, 0xac, 0x2, 0xce, 0x77, 0x35, 0xe, 0xef, 0xc4, 0x5c, 0x1c, 0xf7, 0x54, 0x4, 0x87, 0xa9, 0xa7, 0x64, 0xa7, 0x8f, 0x4, 0xf7, 0x53, 0x58, 0x64, 0x84, 0xd7, 0xa, 0x97, 0xf2, 0xe3]
//License signed from server :)
auto licenseHash = digest::sha256(license);
auto licenseSign = base64::decode(initivexpand2["proof"]);
int state;
assert(ecc_verify_hash((u_char*) licenseSign.c_str(), licenseSign.length(), (u_char*) licenseHash.c_str(), licenseHash.length(), &state, serverPublic.get()) == CRYPT_OK);
cout << "State: " << state << endl;
assert(state == 1);
//EK!
this->idManager.nextPacketId(PacketTypeInfo::Command);
cout << this->idManager.currentPacketId(PacketTypeInfo::Command) << endl;
Command clientek("clientek");
clientek["ek"] = base64::encode((char*) clientPublicKey, 32);
auto rawProof = string((char*) clientPublicKey, 32) + base64::decode(initivexpand2["beta"]);
cout << " -> " << rawProof.length() << endl;
size_t signBufferLength = 120;
char signBuffer[signBufferLength];
prng_state prngState{};
memset(&prngState, 0, sizeof(prngState));
cout << "Data: " << base64::encode(rawProof) << endl;
cout << "KEY: " << this->clientIdentity->privateKey() << endl;
rawProof = digest::sha256(rawProof);
assert(ecc_sign_hash((u_char*) rawProof.data(), rawProof.length(), (u_char*) signBuffer, &signBufferLength, &prngState, find_prng("sprng"), this->clientIdentity->getKeyPair()) == CRYPT_OK);
cout << "ecc_sign_hash() -> " << base64::encode(signBuffer, signBufferLength) << endl;
clientek["proof"] = base64::encode(signBuffer, signBufferLength);
this->sendCommand(clientek, false);
//TODO magic stuff
shared_ptr<ServerPacket> response;
response = readNextPacket();
if (!response) {
errorMessage = "could not get a valid response!";
return false;
}
cout << "Type: " << response->type().name() << endl;
cout << "ID: " << (int) response->data()[0] << " " << (int) response->data()[1] << endl;
LicensePublicKey serverroot;
memcpy(serverroot, public_root, 32);
if(initivexpand2[0].has("root")) {
cout << "Cot costume server root!" << endl;
auto root = base64::decode(initivexpand2["root"]);
memcpy(serverroot, root.data(), 32);
}
cout << "Public root key: " << endl;
for(const auto& e : serverroot)
cout << hex << "0x" << (int) (uint8_t) e << " " << endl;
string sharedData;
this->cryptionHandler->setupSharedSecretNew(alpha, base64::decode(initivexpand2["beta"]), (char*) clientPrivateKey, (char*) chain->generatePublicKey(serverroot).data());
//this->cryptionHandler->setupSharedSecretNew(alpha, base64::decode(initivexpand2["beta"]), (char*) clientPrivateKey, (char*) public_tea_root);
threads::self::sleep_for(milliseconds(250));
Command clientinit("clientinit");
//94ec66de-5940-4e38-b002-970df0cf6c94,62444179-0d99-42ba-a45c-c6b1557d079a,d95f9901-c42d-4bac-8849-7164fd9e2310
//clientinit["client_badges"] = "badges=450f81c1-ab41-4211-a338-222fa94ed157,c9e97536-5a2d-4c8e-a135-af404587a472,94ec66de-5940-4e38-b002-970df0cf6c94"; //,62444179-0d99-42ba-a45c-c6b1557d079a
clientinit["client_nickname"] = "Wolf C++ XX";
clientinit["client_version"] = "3.1.8 [Build: 1516614607]";
clientinit["client_platform"] = "Windows";
clientinit["client_version_sign"] = "gDEgQf/BiOQZdAheKccM1XWcMUj2OUQqt75oFuvF2c0MQMXyv88cZQdUuckKbcBRp7RpmLInto4PIgd7mPO7BQ==";
clientinit["client_input_hardware"] = true;
clientinit["client_output_hardware"] = true;
clientinit["client_default_channel"] = "";
clientinit["client_default_channel_password"] = "";
clientinit["client_server_password"] = "";
clientinit["client_meta_data"] = "";
clientinit["client_key_offset"] = this->clientIdentity->lastValidKeyOffset();
clientinit["client_nickname_phonetic"] = "";
clientinit["client_default_token"] = "";
clientinit["hwid"] = "123,456123123123";
sendCommand(clientinit);
this->autoHandle = true;
/*
response = readNextPacket();
if (!response) {
errorMessage = "could not get a valid response!";
return false;
}
*/
return true;
}

View File

@ -1,115 +0,0 @@
//
// Created by root on 13.10.17.
//
#include "FilteredUDPSocket.h"
#include <iostream>
#include <cstring>
#include <ifaddrs.h>
#include <netinet/udp.h> //Provides declarations for udp header
#include <netinet/ip.h> //Provides declarations for ip header
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
#include <linux/filter.h>
#include <chrono>
#include <zconf.h>
using namespace std;
using namespace std::chrono;
using namespace ts::connection;
FilteredUdpSocket::FilteredUdpSocket() {}
FilteredUdpSocket::~FilteredUdpSocket() {}
bool FilteredUdpSocket::setup(sockaddr_in * remoteAddr) {
srand(system_clock::now().time_since_epoch().count()); // should only be called once
int r = (lrand48() % (50 * 1000)) + 1000; // returns a pseudo-random integer between 0 and RAND_MAX
this->remoteAdress = new sockaddr_in;
memcpy(this->remoteAdress, remoteAddr, sizeof(sockaddr_in));
this->socketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(this->socketDescriptor < 0){
cerr << "Invalid socket create: " << errno << " - " << this->socketDescriptor << " -> " << strerror(errno) << endl;
}
int allow = 1;
setsockopt(this->socketDescriptor, SOL_SOCKET, SO_REUSEADDR, &allow, sizeof(int));
this->localAdress = new sockaddr_in;
memset((char *) this->localAdress, 0, sizeof(sockaddr_in));
localAdress->sin_family = AF_INET;
localAdress->sin_addr.s_addr = htonl(INADDR_ANY);
localAdress->sin_port = htons(r);
/* sudo tcpdump -q udp port 256 -dd */
struct sock_filter code[ ] = {
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 8, 0x000086dd },
{ 0x30, 0, 0, 0x00000014 },
{ 0x15, 2, 0, 0x00000084 },
{ 0x15, 1, 0, 0x00000006 },
{ 0x15, 0, 17, 0x00000011 },
{ 0x28, 0, 0, 0x00000036 },
{ 0x15, 14, 0, 0x00002fbd },
{ 0x28, 0, 0, 0x00000038 },
{ 0x15, 12, 13, 0x00002fbd },
{ 0x15, 0, 12, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 2, 0, 0x00000084 },
{ 0x15, 1, 0, 0x00000006 },
{ 0x15, 0, 8, 0x00000011 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 6, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x0000000e },
{ 0x15, 2, 0, 0x00002fbd },
{ 0x48, 0, 0, 0x00000010 },
{ 0x15, 0, 1, 0x00002fbd },
{ 0x6, 0, 0, 0x00040000 },
{ 0x6, 0, 0, 0x00000000 },
};
struct sock_fprog bpf = {
.len = sizeof(code) / sizeof(*code),
.filter = code,
};
//auto response = setsockopt(this->socketDescriptor, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
//if (response < 0) cerr << "Invalid attach!" << endl;
/* ... bail out ... */
/*
*
if(connect(this->socketDescriptor, (const sockaddr *) remoteAddr, sizeof(sockaddr_in)) < 0){
cerr << "Invalid connect" << endl;
}
*/
if(bind(this->socketDescriptor, (const sockaddr *) localAdress, sizeof(sockaddr_in)) < 0) cout << "XXX" << endl;
return true;
}
void FilteredUdpSocket::close() {
if(this->socketDescriptor > 0) {
shutdown(this->socketDescriptor, SHUT_RDWR);
::close(this->socketDescriptor);
this->socketDescriptor = 0;
}
}
ssize_t FilteredUdpSocket::write(const char *buffer, size_t size) {
return sendto(this->socketDescriptor, buffer, size, 0, (const sockaddr *) this->remoteAdress, sizeof(sockaddr_in));
}
ssize_t FilteredUdpSocket::read(char *buffer, size_t size) {
return recv(this->socketDescriptor, (void *) buffer, size, 0);
}

View File

@ -1,27 +0,0 @@
#pragma once
#include <netinet/in.h>
namespace ts {
namespace connection {
class FilteredUdpSocket {
public:
FilteredUdpSocket();
~FilteredUdpSocket();
bool setup(sockaddr_in*);
void close();
ssize_t read(char* buffer, size_t size);
ssize_t write(const char* buffer, size_t size);
int getSocketDescriptor(){ return socketDescriptor; }
private:
int socketDescriptor;
sockaddr_in* remoteAdress = nullptr;
sockaddr_in* localAdress = nullptr;
};
typedef FilteredUdpSocket UdpSocket;
}
}

View File

@ -1,151 +0,0 @@
//
// Created by wolverindev on 12.10.17.
//
#include <iostream>
#include <cstring>
#include <ifaddrs.h>
#include <netinet/udp.h> //Provides declarations for udp header
#include <netinet/ip.h> //Provides declarations for ip header
#include <arpa/inet.h>
#include "RawUDPSocket.h"
using namespace std;
using namespace ts::connection;
/*
96 bit (12 bytes) pseudo header needed for udp header checksum calculation
*/
struct pseudo_header
{
u_int32_t source_address;
u_int32_t dest_address;
u_int8_t placeholder;
u_int8_t protocol;
u_int16_t udp_length;
};
RawUdpSocket::RawUdpSocket() {}
RawUdpSocket::~RawUdpSocket() {}
uint16_t RawUdpSocket::buildCheckSum(uint16_t* buffer, size_t size) {
register long sum;
unsigned short oddbyte;
register short answer;
sum = 0;
while (size > 1) {
sum += *buffer++;
size -= 2;
}
if (size == 1) {
oddbyte = 0;
*((u_char *) &oddbyte) = *(u_char *) buffer;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum = sum + (sum >> 16);
answer = (short) ~sum;
return (answer);
}
int RawUdpSocket::read(char *buffer, size_t size) {}
int RawUdpSocket::write(const char *buffer, size_t size) {
char datagram[4096];
memset(datagram, 0, 4096);
memcpy(&datagram[sizeof(iphdr) + sizeof(udphdr)], buffer, size);
//IP header
struct iphdr *iph = (struct iphdr *) datagram;
//UDP header
struct udphdr *udph = (struct udphdr *) (datagram + sizeof(struct ip));
//Setup the ip header
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = sizeof(iphdr) + sizeof(udphdr) + size; //Total length
iph->id = htonl(12); //TODO increase
iph->frag_off = 0;
iph->ttl = 255; //Max 255 hops maybe change it to default 64
iph->protocol = IPPROTO_UDP;
iph->saddr = localAdress->sin_addr.s_addr;
iph->daddr = remoteAdress->sin_addr.s_addr;
iph->check = this->buildCheckSum ((unsigned short *) datagram, iph->tot_len);
udph->source = localAdress->sin_port;
udph->dest = remoteAdress->sin_port;
udph->len = htons(8 + size);
size_t csumLength = sizeof(struct pseudo_header) + sizeof(struct udphdr) + size;
char csumData[csumLength];
pseudo_header psh;
//Now the UDP checksum using the pseudo header
psh.source_address = localAdress->sin_addr.s_addr;
psh.dest_address = remoteAdress->sin_addr.s_addr;
psh.placeholder = 0;
psh.protocol = IPPROTO_UDP;
psh.udp_length = htons(sizeof(struct udphdr) + size);
memcpy(csumData , (char*) &psh , sizeof (struct pseudo_header));
memcpy(csumData + sizeof(struct pseudo_header) , udph , sizeof(struct udphdr) + size);
udph->check = buildCheckSum((uint16_t *) csumData, csumLength);
auto written = sendto(this->socketDescriptor, datagram, iph->tot_len, 0, (struct sockaddr *) this->remoteAdress, sizeof(sockaddr));
if(written != iph->tot_len){
cerr << "Invalid write: " << written << endl;
return -1;
}
cout << "Write: " << written << endl;
return size;
}
bool RawUdpSocket::setup(sockaddr_in *remoteAdress) {
this->remoteAdress = new sockaddr_in;
memcpy(this->remoteAdress, remoteAdress, sizeof(sockaddr_in));
this->socketDescriptor = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if(this->socketDescriptor < 0){
if(this->socketDescriptor == EPERM){
cerr << "Invalid permission. Dont have permission to create a new RAW socket!";
return false;
}
cerr << "Invalid socket create: " << errno << " - " << this->socketDescriptor << " -> " << strerror(errno) << endl;
}
//get local addr
this->localAdress = new sockaddr_in;
struct ifaddrs *ifAddrStruct = NULL;
getifaddrs(&ifAddrStruct);
for (ifaddrs* ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr) {
continue;
}
if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
// is a valid IP4 Address
memcpy(this->localAdress, ifa->ifa_addr, sizeof(sockaddr_in));
/*
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
*/
}
/*
else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
// is a valid IP6 Address
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
}
*/
}
if (ifAddrStruct != NULL) freeifaddrs(ifAddrStruct);
this->localAdress->sin_port = 1232;
return true;
}

View File

@ -1,28 +0,0 @@
#pragma once
#include <netinet/in.h>
namespace ts {
namespace connection {
class RawUdpSocket {
public:
RawUdpSocket();
~RawUdpSocket();
bool setup(sockaddr_in*);
int read(char* buffer, size_t size);
int write(const char* buffer, size_t size);
uint16_t buildCheckSum(uint16_t* buffer, size_t size);
int getSocketDescriptor(){ return socketDescriptor; }
private:
int socketDescriptor;
sockaddr_in* remoteAdress = nullptr;
sockaddr_in* localAdress = nullptr;
};
typedef RawUdpSocket UdpSocket;
}
}

View File

@ -1,25 +0,0 @@
cmake_minimum_required(VERSION 3.6)
project(TeamSpeak)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories(../shared/src)
add_definitions(-DLTM_DESC)
set(SOURCE_FILES
main.cpp
src/ProxiedClient.cpp
src/PorxiedClientSock5.cpp
src/TSClient.cpp
)
add_executable(TeamSpeakFloodClient ${SOURCE_FILES})
target_link_libraries(TeamSpeakFloodClient
TeaSpeak
pthread ThreadPool
${TOM_LIBRARIES}
crypto
event
event_pthreads
/usr/local/lib/libjsoncpp.so
)

View File

@ -1,81 +0,0 @@
#include <arpa/inet.h>
#include <string>
#include <cstring>
#include <src/ProxiedClient.h>
#include <event2/thread.h>
#include <iomanip>
using namespace std;
using namespace ts::flood;
void hexout(std::ostream& os, unsigned char c)
{
unsigned char uc = static_cast<unsigned char>(c);
os << std::setw(2) << std::setfill('0') << (unsigned int)uc << ' ';
}
void hexdump(std::ostream& outs, const std::string& s, size_t line_len = 16)
{
std::ostringstream os;
const std::string::size_type slen(s.size());
int i(0);
std::string::size_type pos(0);
const std::streamsize lines(slen / line_len);
const std::streamsize chars(slen % line_len);
std::ios::fmtflags f(os.flags());
os << "Length: " << s.length() << "/" << std::hex << "0x" << s.length() << endl;
for(std::streamsize line = 0; line <= lines - (chars == 0 ? 1 : 0); ++line)
{
os << std::hex << setfill('0') << setw(3) << line * line_len << " | ";
for(i = 0; i < line_len; ++i)
{
if(pos < s.length())
hexout(os, s[pos]);
else os << " ";
pos++;
}
os << " | ";
if(pos - line_len < s.length()){
auto av = s.substr(pos - line_len);
for(char c : av.substr(0, min(av.length(), line_len))){
if(isprint(c))
os << c << " ";
else
os << "." << " ";
}
}
os << '\n';
}
os.flags(f);
outs << os.str() << endl;
}
int main(int argc, char** argv){
sockaddr_in remoteAddress{}, proxyAddress{};
memset(&remoteAddress, 0, sizeof(remoteAddress));
memset(&proxyAddress, 0, sizeof(proxyAddress));
proxyAddress.sin_family = AF_INET;
proxyAddress.sin_port = htons(1085);
proxyAddress.sin_addr.s_addr = inet_addr("185.89.100.17");
/*
proxyAddress.sin_family = AF_INET;
proxyAddress.sin_port = htons(1080);
proxyAddress.sin_addr.s_addr = inet_addr("54.38.22.7");
*/
remoteAddress.sin_family = AF_INET;
remoteAddress.sin_port = htons(1100);
remoteAddress.sin_addr.s_addr = inet_addr("87.106.252.164");
assert(evthread_use_pthreads() == 0);
event_base* evBase = event_base_new();
ProxiedClient client(evBase, proxyAddress, remoteAddress);
client.connect();
event_base_dispatch(evBase);
}

View File

@ -1,111 +0,0 @@
#include <mutex>
#include <arpa/inet.h>
#include <ThreadPool/Thread.h>
#include "ProxiedClient.h"
using namespace std;
using namespace std::chrono;
using namespace ts::flood;
#define CERROR(msg) \
do { \
cerr << msg << endl;\
this->disconnect();\
return;\
} while(0)
static int port = 10000;
static threads::Mutex portLock;
void ProxiedClient::handleProxyMessage(const std::string &msg) {
if(this->state == PROXY_INIT_METHODS){
if(msg[0] != 0x05) CERROR("Invalid proxy version response (methode exchange)");
if(msg[1] != 0x00) CERROR("Invalid respond methode");
this->state = PROXY_INIT_CONNECTION;
char buffer[128];
int index = 0;
buffer[index++] = 0x05; //Version
buffer[index++] = 0x03; //Udp weiterleitung
buffer[index++] = 0x00; //Resv
buffer[index++] = 0x01; //Addr type = IPv4
auto addr = IPv4{this->remoteAddr->sin_addr.s_addr};
buffer[index++] = addr._1;
buffer[index++] = addr._2;
buffer[index++] = addr._3;
buffer[index++] = addr._4;
buffer[index++] = (ntohs(this->remoteAddr->sin_port) >> 8) & 0xFF;
buffer[index++] = (ntohs(this->remoteAddr->sin_port) >> 0) & 0xFF;
this->sendMessage(string(buffer, index));
} else if(this->state = PROXY_INIT_CONNECTION){
cout << "res!" << endl;
int index = 0;
if(msg[index++] != 0x05) CERROR("Invalid proxy version response (connection request)");
if(msg[index++] != 0x00) CERROR("Could not create connection (" + to_string((int) msg[1]) + ")");
if(msg[index++] != 0x00) CERROR("Invalid proxy rsv response (connection request)");
if(msg[index++] != 0x01) CERROR("Invalid proxy ip response type");
auto rAddr = IPv4{};
rAddr._1 = msg[index++];
rAddr._2 = msg[index++];
rAddr._3 = msg[index++];
rAddr._4 = msg[index++];
uint16_t pHigh = ((uint16_t) msg[index++]) & 0xFF;
uint16_t pLow = ((uint16_t) msg[index++]) & 0xFF;
uint16_t rPort = (pHigh << 8) | pLow;
cout << "Got udp relay " << rAddr.string() << ":" << rPort << endl;
//Delete old connection
//shutdown(this->fileDescriptor, SHUT_RDWR);
event_del(this->wEvent);
event_del(this->rEvent);
this->fileDescriptor = 0;
//Setup relay
this->relayAddr = new sockaddr_in{};
memset(relayAddr, 0, sizeof(*relayAddr));
relayAddr->sin_family = AF_INET;
relayAddr->sin_port = htons(rPort);
relayAddr->sin_addr.s_addr = rAddr.addr;
cout << "Relay addr: " << inet_ntoa(relayAddr->sin_addr) << ":" << ntohs(relayAddr->sin_port) << endl;
this->localAddr = new sockaddr_in{};
memset(localAddr, 0, sizeof(*localAddr));
localAddr->sin_family = AF_INET;
{
lock_guard<threads::Mutex> l(portLock);
localAddr->sin_port = this->remoteAddr->sin_port; // = htons(10000 + (port++ % 30000));
}
localAddr->sin_addr.s_addr = htonl(INADDR_ANY);
this->fileDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
cout << "fd -> " << this->fileDescriptor << endl;
int allow = 1;
if(setsockopt(this->fileDescriptor, SOL_SOCKET, SO_REUSEADDR, &allow, sizeof(int)) < 0) CERROR("Could not enable reuse addr");
if(bind(this->fileDescriptor, reinterpret_cast<const sockaddr *>(this->localAddr), sizeof(*this->localAddr)) < 0) CERROR("Could nto bind to relay");
cout << "Bind on " << inet_ntoa(this->localAddr->sin_addr) << ":" << ntohs(this->localAddr->sin_port) << endl;
this->state = PROXY_CONNECTED;
this->rEvent = event_new(this->evBase, this->fileDescriptor, EV_READ | EV_PERSIST, ProxiedClient::handleEventRead, this);
this->wEvent = event_new(this->evBase, this->fileDescriptor, EV_WRITE, ProxiedClient::handleEventWrite, this);
event_add(rEvent, nullptr);
threads::Thread([&](){
threads::self::sleep_for(seconds(1));
this->proxyInizalisized();
});
}
}
void ProxiedClient::requestProxyConnection() {
char buffer[3];
buffer[0] = 0x05; //Version
buffer[1] = 1; //One methode
buffer[2] = 0x00; //No auth required
this->sendMessage(string(buffer, 3));
}

View File

@ -1,175 +0,0 @@
#include <mutex>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include "ProxiedClient.h"
#include "TSClient.h"
using namespace std;
using namespace ts::flood;
ProxiedClient::ProxiedClient(event_base* base, const sockaddr_in &proxyAddr, const sockaddr_in &remoteAddr) : evBase(base) {
this->proxyAddr = new sockaddr_in{};
this->remoteAddr = new sockaddr_in{};
memcpy(this->proxyAddr, &proxyAddr, sizeof(proxyAddr));
memcpy(this->remoteAddr, &remoteAddr, sizeof(proxyAddr));
this->client = new TSClient(this);
}
ProxiedClient::~ProxiedClient() {
delete this->proxyAddr;
delete this->remoteAddr;
}
#define CERR(msg) \
do { \
cerr << "Could not connect: " << msg << "(" << errno << "/" << strerror(errno) << ")" << endl; \
return false; \
} while(0)
#if defined(TCP_CORK) && !defined(TCP_NOPUSH)
#define TCP_NOPUSH TCP_CORK
#endif
static int enabled = 1;
static int disabled = 0;
bool ProxiedClient::connect() {
assert(this->state == ProxyState::PROXY_UNCONNECTED);
TAILQ_INIT(&this->writeQueue);
this->fileDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if(this->fileDescriptor < 0) CERR("Socket setup failed");
if(::connect(this->fileDescriptor, reinterpret_cast<const sockaddr *>(this->proxyAddr), sizeof(*this->proxyAddr)) < 0) CERR("connect() failed");
if(setsockopt(this->fileDescriptor, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled)) < 0) CERR("could not set reuse addr");
if(setsockopt(this->fileDescriptor, IPPROTO_TCP, TCP_NOPUSH, &disabled, sizeof(disabled)) < 0) CERR("could not set no push");
cout << "Connected to " << inet_ntoa(this->proxyAddr->sin_addr) << endl;
this->rEvent = event_new(this->evBase, this->fileDescriptor, EV_READ | EV_PERSIST, ProxiedClient::handleEventRead, this);
this->wEvent = event_new(this->evBase, this->fileDescriptor, EV_WRITE, ProxiedClient::handleEventWrite, this);
event_add(rEvent, nullptr);
this->state = ProxyState::PROXY_INIT_METHODS;
this->requestProxyConnection();
return true;
}
void ProxiedClient::disconnect() {
this->closeConnection();
}
void ProxiedClient::closeConnection() {
{
lock_guard<threads::Mutex> lock(this->stateLock);
if(this->state == PROXY_UNCONNECTED) return;
this->state = PROXY_UNCONNECTED;
}
event_del(this->wEvent);
event_del(this->rEvent);
this->wEvent = nullptr;
this->rEvent = nullptr;
}
void ProxiedClient::sendMessage(const std::string& message) {
buffer::RawBuffer* buffer;
if(this->state != PROXY_CONNECTED){
buffer = new buffer::RawBuffer{message.length()};
memcpy(buffer->buffer, message.data(), message.length());
} else {
cout << "Send " << message.length() << " bytes with relay" << endl;
int relayHeaderLength = 2 + 1 + 1 + 4 + 2;
buffer = new buffer::RawBuffer{relayHeaderLength + message.length()};
buffer->index = 0;
char preBuffer[relayHeaderLength];
preBuffer[0] = 0x00;
preBuffer[1] = 0x00;
preBuffer[2] = 0x00;
preBuffer[3] = 0x01;
IPv4 addr{this->relayAddr->sin_addr.s_addr};
preBuffer[4] = addr._1;
preBuffer[5] = addr._2;
preBuffer[6] = addr._3;
preBuffer[7] = addr._4;
preBuffer[8] = (ntohs(this->relayAddr->sin_port) >> 8) & 0xFF;
preBuffer[9] = (ntohs(this->relayAddr->sin_port) >> 0) & 0xFF;
//memset(&preBuffer[4], 0, 6);
memcpy(&buffer->buffer[0], preBuffer, relayHeaderLength);
memcpy(&buffer->buffer[relayHeaderLength], message.data(), message.length());
}
{
lock_guard<threads::Mutex> lock(this->queueLock);
TAILQ_INSERT_TAIL(&this->writeQueue, buffer, tail);
}
event_add(this->wEvent, nullptr);
}
void ProxiedClient::handleMessage(const std::string &message) {
if(this->state == PROXY_UNCONNECTED) return;
if(this->state == PROXY_CONNECTED) return; //TODO
this->handleProxyMessage(message);
}
extern void hexdump(std::ostream& outs, const std::string& s, size_t line_len = 16);
void ProxiedClient::handleEventWrite(int fd, short, void* ptrClient) {
auto* client = static_cast<ProxiedClient *>(ptrClient);
buffer::RawBuffer* buffer = nullptr;
{
lock_guard<threads::Mutex> lock(client->queueLock);
buffer = TAILQ_FIRST(&client->writeQueue);
if(!buffer) return;
ssize_t writtenBytes = 0;
if(client->state == PROXY_CONNECTED){
cout << "Write bytes to relay - " << fd << " - " << inet_ntoa(client->relayAddr->sin_addr) << ":" << ntohs(client->relayAddr->sin_port) << endl;
hexdump(cout, string((const char*) buffer->buffer, buffer->length));
writtenBytes = sendto(fd, buffer->buffer, buffer->length, 0, (const sockaddr *) client->relayAddr, sizeof(*client->relayAddr));
} else
writtenBytes = send(fd, &buffer->buffer[buffer->index], buffer->length - buffer->index, 0);
buffer->index += writtenBytes;
cout << "Written: " << writtenBytes << endl;
if(buffer->index >= buffer->length || client->state == PROXY_CONNECTED) {
TAILQ_REMOVE(&client->writeQueue, buffer, tail);
delete buffer;
}
if(!TAILQ_EMPTY(&client->writeQueue))
event_add(client->wEvent, nullptr);
}
}
void ProxiedClient::handleEventRead(int fd, short, void* ptrClient) {
auto* client = static_cast<ProxiedClient *>(ptrClient);
char buffer[1024];
sockaddr_in remoteAddr{};
socklen_t remoteAddrSize = sizeof(remoteAddr);
auto read = recvfrom(fd, buffer, 1024, MSG_DONTWAIT, reinterpret_cast<sockaddr *>(&remoteAddr), &remoteAddrSize);
cout << "Read " << read << " bytes" << endl;
if(read < 0){
if(errno == EWOULDBLOCK) return;
cerr << "Invalid read: " << errno << "/" << strerror(errno) << endl;
client->disconnect();
return;
} else if(read == 0){
cerr << "Client hangs up!" << endl;
client->closeConnection();
return;
}
hexdump(cout, string(buffer, read));
client->handleMessage(string(buffer, read));
}
void ProxiedClient::proxyInizalisized() {
this->client->startConnect();
}

View File

@ -1,72 +0,0 @@
#pragma once
#include <string>
#include <netinet/in.h>
#include <misc/queue.h>
#include <protocol/buffers.h>
#include <event.h>
namespace ts {
namespace flood {
union IPv4 {
uint32_t addr;
struct __attribute__ ((__packed__)) {
uint8_t _1;
uint8_t _2;
uint8_t _3;
uint8_t _4;
};
inline std::string string(){
std::stringstream ss;
ss << (int) _1 << "." << (int) _2 << "." << (int) _3 << "." << (int) _4;
return ss.str();
}
};
class TSClient;
enum ProxyState {
PROXY_UNCONNECTED,
PROXY_INIT_METHODS,
PROXY_INIT_CONNECTION,
PROXY_CONNECTED
};
class ProxiedClient {
public:
ProxiedClient(event_base*,const sockaddr_in& proxyAddr, const sockaddr_in& remoteAddr);
~ProxiedClient();
bool connect();
void disconnect();
void closeConnection();
void handleMessage(const std::string& message);
void sendMessage(const std::string &);
private:
static void handleEventRead(int, short, void*);
static void handleEventWrite(int, short, void*);
void requestProxyConnection();
void handleProxyMessage(const std::string &);
void proxyInizalisized();
event_base* evBase = nullptr;
event* rEvent = nullptr;
event* wEvent = nullptr;
int fileDescriptor;
ProxyState state = ProxyState::PROXY_UNCONNECTED;
threads::Mutex stateLock;
sockaddr_in* proxyAddr = nullptr;
sockaddr_in* relayAddr = nullptr;
sockaddr_in* localAddr = nullptr;
sockaddr_in* remoteAddr = nullptr;
TAILQ_HEAD(, buffer::RawBuffer) writeQueue;
threads::Mutex queueLock;
TSClient* client = nullptr;
};
}
}

View File

@ -1,108 +0,0 @@
//
// Created by wolverindev on 06.01.18.
//
#include "TSClient.h"
using namespace std;
using namespace std::chrono;
using namespace ts::flood;
using namespace ts::protocol;
TSClient::TSClient(ProxiedClient* con) : connection(con) {
this->cryptionHandler = new connection::CryptionHandler();
this->cryptionHandler->reset();
}
TSClient::~TSClient() {}
void TSClient::handleMessageRead(const std::string& message) {
if(message.length() < MAC_SIZE + SERVER_HEADER_SIZE) {
cerr << "Invalid pkt length!" << endl;
return;
}
shared_ptr<ServerPacket> packet = make_shared<ServerPacket>(message);
cout << "Having packet " << packet->type().name() << endl;
}
void TSClient::sendPacket(ts::protocol::ClientPacket &packet, int32_t packetId) {
size_t maxDataLength = 500 - packet.header().length();
if(packet.data().length() > maxDataLength){
cout << "Split packet" << endl;
string error;
/*
if(!compressPacket(&packet, error)){
cerr << "Compress error!" << endl;
return;
}
packet.enableFlag(PacketFlag::Compressed);
*/
if(packet.data().length() > maxDataLength){
std::vector<ClientPacket*> siblings;
ClientPacket* root = new ClientPacket(packet.type(), packet.flagMask(), packet.data());
root->enableFlag(PacketFlag::Fragmented);
//assert(root->hasFlag(PacketFlag::Compressed));
siblings.push_back(root);
//Max len - mac - header
while(siblings.back()->data().length() > maxDataLength){
auto overhead = siblings.back()->data().substr(maxDataLength);
siblings.back()->data(siblings.back()->data().substr(0, maxDataLength));
ClientPacket* sib = new ClientPacket(packet.type(), packet.flagMask(), overhead);
sib->toggle(PacketFlag::Fragmented, false);
siblings.push_back(sib);
}
siblings.back()->enableFlag(PacketFlag::Fragmented);
for(auto elm : siblings){
sendPacket(*elm);
delete elm;
}
return;
}
}
if (packetId == -1)
packet.applyPacketId(pktIdManager);
else packet.applyPacketId((uint16_t) packetId, 0);
packet.clientId(this->clientId);
string error = "success";
if (!this->cryptionHandler->progressPacketOut(&packet, error)) {
cerr << "Invalid crypt -> " << error << endl;
return;
}
this->connection->sendMessage(packet.mac() + packet.header() + packet.data());
}
const int InitVersionLength = 4;
const uint8_t InitVersion[InitVersionLength] = {0x06, 0x3b, 0xEC, 0xE9};
void TSClient::startConnect() {
int maxBufferSize = 512;
size_t bufferIndex = 0;
uint8_t buffer[maxBufferSize];
string error = "success";
memcpy(buffer, InitVersion, InitVersionLength);
bufferIndex += InitVersionLength;
buffer[bufferIndex++] = 0x00; //Login state
int64_t millis = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
memcpy(&buffer[5], &millis, 4);
bufferIndex += 4;
//generate the alpha key
for (int i = 0; i < 4; i++) buffer[bufferIndex++] = (uint8_t) std::rand();
bufferIndex += 8; //Reserved bytes
ClientPacket pkt(ts::protocol::PacketTypeInfo::Init1, string((char *) buffer, bufferIndex));
pkt.clientId(0);
pkt.toggle(ts::protocol::PacketFlag::Unencrypted, true);
this->sendPacket(pkt, 101);
}

View File

@ -1,36 +0,0 @@
#pragma once
#include "ProxiedClient.h"
#include <string>
#include <Definitions.h>
#include <protocol/CryptionHandler.h>
namespace ts {
namespace flood {
enum TSClientConnectionState {
TSC_UNCONNECTED,
TSC_PRE,
TSC_RSA,
TSC_HIGH,
TSC_CONNECTED
};
class TSClient {
public:
TSClient(ProxiedClient*);
~TSClient();
void startConnect();
void handleMessageRead(const std::string&);
void sendPacket(ts::protocol::ClientPacket &packet, int32_t packetId = -1);
private:
ProxiedClient* connection;
TSClientConnectionState state = TSClientConnectionState::TSC_UNCONNECTED;
protocol::PacketIdManager pktIdManager;
ts::connection::CryptionHandler* cryptionHandler = nullptr;
ClientId clientId = 0;
};
}
}

View File

@ -345,6 +345,19 @@ HWID_REGEX(ios, "^[A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}$"
CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
TIMING_START(timings);
{
lock_guard<threads::Mutex> lock(this->server->join_attempts_lock);
auto inetAddr = this->getPeerIp();
if(config::voice::clientConnectLimit > 0 && this->server->join_attempts[inetAddr] + 1 > config::voice::clientConnectLimit)
return {findError("client_is_flooding"), "To many joins per second per ip"};
if(config::voice::connectLimit > 0 && this->server->join_attempts["_"] + 1 > config::voice::connectLimit)
return {findError("client_is_flooding"), "To many joins per second"};
this->server->join_attempts[inetAddr]++;
this->server->join_attempts["_"]++;
}
TIMING_STEP(timings, "join atmp c");
if(!DatabaseHelper::assignDatabaseId(this->server->getSql(), this->server->getServerId(), _this.lock())) return {findError("vs_critical"), "Could not assign database id!"};
TIMING_STEP(timings, "db assign ");
this->server->getGroupManager()->enableCache(this->getClientDatabaseId());
@ -427,18 +440,6 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
debugMessage(this->getServerId(), "{} Got client init. (HWID: {})", CLIENT_STR_LOG_PREFIX, this->getHardwareId());
TIMING_STEP(timings, "props apply");
{
lock_guard<threads::Mutex> lock(this->server->join_attempts_lock);
auto inetAddr = this->getPeerIp();
if(config::voice::clientConnectLimit > 0 && this->server->join_attempts[inetAddr] + 1 > config::voice::clientConnectLimit)
return {findError("client_is_flooding"), "To many joins per second per ip"};
if(config::voice::connectLimit > 0 && this->server->join_attempts["_"] + 1 > config::voice::connectLimit)
return {findError("client_is_flooding"), "To many joins per second"};
this->server->join_attempts[inetAddr]++;
this->server->join_attempts["_"]++;
}
TIMING_STEP(timings, "join atmp c");
auto permissions_list = this->permissionValues(permission::PERMTEST_ORDERED, {
permission::b_virtualserver_join_ignore_password,
permission::b_client_ignore_bans,