Last active
March 7, 2024 00:40
-
-
Save ldmsys/db228996c9696c7ad59a579abb6e7afd to your computer and use it in GitHub Desktop.
FakeMCServer Minimal Edition (requires 3 syscall: read(), write(), close())
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define MC_MTU 1500 | |
#define MC_COLOR_PREFIX "\xc2\247" | |
#define MC_MOTD MC_COLOR_PREFIX "b" MC_COLOR_PREFIX "l" "FakeMCServer Test" | |
#define MC_KICK_MESSAGE "You are not white-listed on this server!" | |
typedef int type_debug_func (const char*, ...); | |
size_t mc_varintSize(unsigned char* varint) { | |
int i; | |
for(i=0;i<4;i++) if((varint[i] & 0x80) == 0) break; | |
return i+1; | |
} | |
int mc_varintToint(unsigned char* varint) { | |
int value = 0; | |
char currentByte; | |
for(int i=0;i<4;i++) { | |
currentByte = varint[i]; | |
value |= (currentByte & 0x7f) << i*7; | |
if ((currentByte & 0x80) == 0) break; | |
} | |
return value; | |
} | |
size_t mc_intTovarint(int data, unsigned char* varint) { | |
int i; | |
for (i=0; i<4; i++) { | |
if ((data & ~0x7f) == 0) { | |
varint[i] = data; | |
break; | |
} | |
varint[i] = (data & 0x7f) | 0x80; | |
data >>= 7; | |
} | |
return i+1; | |
} | |
size_t mc_appendLengthvarint(char* string, size_t length, char* mcstring) { | |
unsigned char len[4]; | |
int i; | |
size_t headerlen; | |
headerlen = mc_intTovarint(length, len); | |
for (i=0; i<headerlen; i++) mcstring[i] = len[i]; | |
for (i=0; i<length; i++) mcstring[i+headerlen] = string[i]; | |
return headerlen+length; | |
} | |
size_t mc_strlen(char* string) { | |
size_t cnt; | |
for(cnt=0;(cnt<MC_MTU && string[cnt] != '\0'); cnt++) {} | |
return cnt; | |
} | |
void mc_handle_session(int fd, type_debug_func debug_func) { | |
int i, n, dn, expected_packet_size, mode, yebiopt, protocol; | |
unsigned char buf[MC_MTU], returnbuf[MC_MTU], yebibuf[MC_MTU], packedJSON[MC_MTU], packetID, payloadsize_varint[4]; | |
char *json, *motd_json, *kick_json; | |
size_t payloadsize, lengthsize, final_size, sz_i; | |
motd_json = "{\"version\": {\"name\": \"ldmsys 1.12.2\", \"protocol\":340},\"players\":{\"max\":99999,\"online\": 0,\"sample\":[]},\"description\":{\"text\": \"" MC_MOTD "\"}}"; | |
kick_json = "{\"text\": \"" MC_KICK_MESSAGE "\"}"; | |
i = n = expected_packet_size = mode = yebiopt = protocol = 0; | |
(!!debug_func) && debug_func("One connected!\n"); | |
while (1) { | |
if (yebiopt) { | |
(!!debug_func) && debug_func("Restoring from yebi! %d\n", yebiopt); | |
n = yebiopt; | |
for (i=0; i<yebiopt; i++) buf[i] = yebibuf[i]; | |
yebiopt = 0; | |
} else { | |
(!!debug_func) && debug_func("Reading... %d\n", mode); | |
dn = read(fd, buf+n, 1500-n); | |
if (dn <= 0) { | |
close(fd); | |
break; | |
} | |
n += dn; | |
(!!debug_func) && debug_func("Read! +%d=%d\n", dn,n); | |
} | |
if(expected_packet_size == 0) { | |
expected_packet_size = mc_varintToint(buf); | |
(!!debug_func) && debug_func("Expected packet size: %d\n", expected_packet_size); | |
} | |
if(expected_packet_size == 0) continue; | |
if(n < expected_packet_size + mc_varintSize(buf)) { | |
(!!debug_func) && debug_func("Johnbeo! %d < %d\n", n, expected_packet_size + mc_varintSize(buf)); | |
continue; | |
} else if(n > expected_packet_size + mc_varintSize(buf)) { | |
(!!debug_func) && debug_func("Moving! %d > %d\n", n, expected_packet_size + mc_varintSize(buf)); | |
for (i=0; i<n-expected_packet_size; i++) | |
yebibuf[i] = *(buf+expected_packet_size+mc_varintSize(buf)+i); | |
yebiopt = n-expected_packet_size-mc_varintSize(buf); | |
n = expected_packet_size + mc_varintSize(buf); | |
} | |
// Complete Packet Received | |
packetID = buf[mc_varintSize(buf)]; | |
(!!debug_func) && debug_func("Packet done! %x %x %x %x %x (%d)\n", buf[0], buf[1], buf[2], buf[3], buf[4], mc_varintSize(buf)); | |
if(mode == 0) { // pre-handshaking | |
protocol = mc_varintToint(buf+mc_varintSize(buf)+1); | |
mode = buf[expected_packet_size]; // new mode | |
(!!debug_func) && debug_func("Handshaking! %d\n", mode); | |
if(packetID != 0 || mode > 2 || mode <= 0) { | |
// Undefined behavior | |
(!!debug_func) && debug_func("Undefined behavior! %d %d\n", packetID, mode); | |
close(fd); break; | |
} | |
} else if(mode == 1 || mode == 2) { | |
(!!debug_func) && debug_func("Respond Mode! %d\n", packetID); | |
if (packetID == 0) { // MOTD Request | |
// json should vary on mode == 1 or mode == 2, ping and kick respectively. | |
json = (mode - 1) ? kick_json : motd_json; | |
payloadsize = mc_appendLengthvarint(json, mc_strlen(json), (void*)packedJSON); | |
lengthsize = mc_intTovarint(payloadsize+1, payloadsize_varint); | |
for (sz_i=0; sz_i<lengthsize; sz_i++) returnbuf[sz_i] = payloadsize_varint[sz_i]; | |
returnbuf[lengthsize] = 0x00; | |
for (sz_i=0; sz_i<payloadsize; sz_i++) returnbuf[lengthsize+1+sz_i] = packedJSON[sz_i]; | |
(!!debug_func) && debug_func("Sent JSON! 1 %d %d %d\n", payloadsize, lengthsize, 1 + payloadsize + lengthsize); | |
write(fd, returnbuf, 1 + payloadsize + lengthsize); | |
} else if(packetID == 1) { // Ping Request | |
if (mode == 1) | |
write(fd, buf, expected_packet_size+mc_varintSize(buf)); // Send back the full packet | |
else { | |
close(fd); // Undefined behavior | |
break; | |
} | |
} | |
} | |
n = expected_packet_size = 0; | |
for (i=0; i<MC_MTU; i++) buf[i] = 0; | |
} | |
(!!debug_func) && debug_func("Got out of loop!\n"); | |
close(fd); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment