Advertisement
Guest User

integrity.wasm (557fd3a402e23aaa204c2c1f313ba2e8ee2e4b16b56b75fe40e444e9da12e491)

a guest
Jun 3rd, 2024
1,681
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 24.66 KB | None | 0 0
  1. // Artifact: integrity.wasm (557fd3a402e23aaa204c2c1f313ba2e8ee2e4b16b56b75fe40e444e9da12e491)
  2. // Date: 06-02-2024
  3. // Toolchain: emscript 3.1.56
  4. // Build: emcc -O3 -sASYNCIFY -sENVIRONMENT=web -sFETCH -lwebsocket.js integrity.c -o integrity
  5. // Description: WASM module for protecting the integrity of https://soyjack.party/
  6. //
  7. // Summary:
  8. // There are 2 main objectives of this module:
  9. // - Reporting if tuxler is detected as open when the module started
  10. // - Replying to commands from the integrity server located at wss://soyjak.party/ws
  11. // The integrity server is able to send arbitrary javascript to be run on the client and
  12. // have a result be returned to the server.
  13. // Additionally, there is some functionality built into the module itself for:
  14. // - Reporting whether Discord was detected as open when the module started
  15. // - Reporting the timezone of the client
  16. //
  17. // As expected of C, UNIX brain damage continues to result in people making memory errors.
  18. //
  19. // Decompilation Status:
  20. // This decompilation is functionally accurate, but it is not quite a perfect decompilation.
  21. // The following issues exist preventing the exact artifact to be compilable from this file:
  22. // - The order of setting the command and the echo for replying to CMD_ECHO is swapped.
  23. // - The signature info char* for getTimezoneOffset is stored 1 off from
  24. //   where it should be on the stack.
  25. // - The code for handling CMD_TIMEZONE is being moved to the end of the
  26. //   function by the branch fold LLVM optimization pass.
  27.  
  28. #include <emscripten.h>
  29. #include <emscripten/fetch.h>
  30. #include <emscripten/websocket.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33.  
  34. #define CMD_ECHO       0x1
  35. #define CMD_TIMEZONE   0x2
  36. #define CMD_FINISH     0x3
  37. #define CMD_EVAL       0x4
  38. #define CMD_DISCORD    0x5
  39. #define CMD_NO_DISCORD 0x6
  40.  
  41. #define CMD_EVAL_VOID   0x0
  42. #define CMD_EVAL_INT32  0x1
  43. #define CMD_EVAL_DOUBLE 0x2
  44. #define CMD_EVAL_STRING 0x3
  45.  
  46. #define ECHO_KEY     0x2f497cdd
  47. #define TIMEZONE_KEY 0xd19aabff
  48.  
  49. unsigned char eval_key[1024] = {
  50.     0x64, 0x43, 0x34, 0x9a, 0xff, 0x1d, 0xed, 0xef, 0x0, 0x47, 0xde, 0xba, 0xbd, 0xa9, 0x2f, 0x41,
  51.     0xcb, 0x6d, 0x6, 0x5a, 0x87, 0x51, 0x9e, 0xaa, 0x28, 0x42, 0x26, 0x51, 0xd9, 0x90, 0xb3, 0xb5,
  52.     0xf0, 0x1b, 0x93, 0x77, 0x95, 0xbf, 0x82, 0xea, 0x53, 0x27, 0x7c, 0xc4, 0xd8, 0xf2, 0x51, 0xc5,
  53.     0x45, 0x21, 0x71, 0x5d, 0x37, 0x4, 0x2, 0xa, 0x73, 0x5d, 0x23, 0x80, 0xce, 0xd1, 0xb6, 0xfe,
  54.     0xe3, 0xa0, 0xcb, 0xbc, 0x0, 0xfe, 0xdc, 0x21, 0x51, 0xef, 0x50, 0x73, 0xdd, 0x64, 0x72, 0x99,
  55.     0x1c, 0xff, 0xb, 0x44, 0xa, 0x6f, 0xd7, 0xc6, 0x25, 0x84, 0x21, 0xc1, 0xec, 0x37, 0x85, 0x92,
  56.     0xc1, 0xcf, 0x63, 0x57, 0xdd, 0x2e, 0x4e, 0xdb, 0x72, 0x53, 0xad, 0x4c, 0x7e, 0x28, 0xef, 0xf4,
  57.     0x75, 0xc1, 0xb9, 0x88, 0xda, 0x94, 0xb8, 0xbe, 0x1d, 0x42, 0x84, 0x6, 0xc1, 0xfe, 0x19, 0xf8,
  58.     0x71, 0xaf, 0x2a, 0xcf, 0xa8, 0x5c, 0xf4, 0x9f, 0xf4, 0xe9, 0xea, 0xd0, 0x3f, 0x54, 0x12, 0x84,
  59.     0x98, 0x1d, 0x82, 0x5a, 0xbb, 0x5e, 0xb7, 0x8c, 0xe6, 0x55, 0x14, 0xcb, 0x95, 0x47, 0x4c, 0x5c,
  60.     0xe4, 0xa3, 0xb8, 0x41, 0x3d, 0x30, 0x71, 0x38, 0xc6, 0xab, 0x53, 0xbe, 0xb2, 0x59, 0xae, 0x51,
  61.     0xde, 0x1b, 0xbd, 0xb6, 0xb9, 0x5, 0x75, 0x85, 0x4f, 0x74, 0x7b, 0x7f, 0xc9, 0x81, 0xa1, 0xa,
  62.     0xcc, 0x80, 0xe7, 0x28, 0x8f, 0x1, 0x4e, 0x12, 0x44, 0x5, 0x2a, 0x57, 0x8e, 0x99, 0x38, 0x59,
  63.     0x97, 0x3d, 0xde, 0x57, 0xc3, 0x45, 0xae, 0x81, 0x23, 0xd7, 0x1a, 0x94, 0xf0, 0xf3, 0xb, 0x3e,
  64.     0x29, 0x64, 0xf4, 0xe2, 0xdd, 0x1a, 0xc7, 0xc2, 0xa2, 0xc, 0x4a, 0x1a, 0xba, 0x6f, 0x15, 0xa8,
  65.     0x9c, 0xe1, 0xfa, 0xb5, 0x9a, 0x1c, 0xc7, 0x7c, 0xf9, 0x4e, 0x2c, 0x14, 0x79, 0xb8, 0xb7, 0x94,
  66.     0xa6, 0xe5, 0x54, 0xbb, 0xa, 0xe3, 0x4c, 0x67, 0xab, 0x35, 0xec, 0x6d, 0xbc, 0x5f, 0x13, 0x8e,
  67.     0xa4, 0x78, 0xf5, 0xeb, 0xfe, 0x72, 0xc9, 0x87, 0x45, 0x26, 0xc1, 0x55, 0x92, 0x39, 0x8d, 0xbb,
  68.     0xc0, 0x4e, 0xb9, 0x77, 0x33, 0x2c, 0x62, 0x9e, 0xfb, 0xb5, 0xbe, 0x4c, 0xae, 0xe1, 0xcd, 0xdf,
  69.     0x89, 0x38, 0x4, 0xd7, 0x42, 0xc9, 0xf8, 0xe3, 0xb3, 0x1f, 0x6b, 0xbe, 0x99, 0x35, 0xdd, 0xcf,
  70.     0x94, 0x16, 0xd7, 0x12, 0x9, 0xcb, 0x1e, 0xe9, 0xef, 0x6f, 0x35, 0x50, 0x2, 0x2d, 0x13, 0x5a,
  71.     0x69, 0x62, 0x3a, 0xc8, 0xf5, 0x22, 0xa5, 0xb6, 0x35, 0x19, 0xc2, 0x78, 0x4e, 0xa2, 0x5e, 0x97,
  72.     0x74, 0x25, 0x86, 0x73, 0x25, 0x61, 0x92, 0xcf, 0x92, 0x12, 0xe5, 0xf8, 0xb1, 0x2, 0x26, 0x5e,
  73.     0x9a, 0x5a, 0x13, 0x14, 0xd0, 0x2f, 0x3d, 0xe3, 0x92, 0xb, 0xa7, 0x9b, 0x42, 0x86, 0xfc, 0xdc,
  74.     0x8, 0xd4, 0x39, 0x16, 0x2e, 0xd1, 0x32, 0x27, 0xa, 0xf8, 0xc1, 0x80, 0xc2, 0xf2, 0x49, 0xef,
  75.     0x7f, 0xe2, 0x3b, 0x91, 0x93, 0xd5, 0xb2, 0x1f, 0x90, 0x5e, 0xee, 0xca, 0xb2, 0x4b, 0x2a, 0x2,
  76.     0xb9, 0x9d, 0x1a, 0x35, 0xf6, 0x2, 0x76, 0x2d, 0x37, 0x1d, 0x7f, 0x6b, 0x0, 0x88, 0x2a, 0x90,
  77.     0xf, 0xd0, 0x9, 0xe8, 0x45, 0x8d, 0xe7, 0x6d, 0xb9, 0x9b, 0xac, 0x11, 0x75, 0x5d, 0xcf, 0xe2,
  78.     0x9f, 0x71, 0x12, 0x46, 0xcd, 0x27, 0xdb, 0x9b, 0xa7, 0xb6, 0x69, 0x36, 0x1b, 0x8f, 0xa3, 0x46,
  79.     0xda, 0xeb, 0x70, 0xfd, 0x69, 0xa1, 0x2c, 0x51, 0x1f, 0x97, 0xb3, 0xb1, 0x4b, 0x82, 0xc, 0xef,
  80.     0xca, 0x4e, 0xca, 0x88, 0x57, 0xfa, 0x1f, 0x25, 0x25, 0xbb, 0xb0, 0x5e, 0x5, 0xfb, 0xf4, 0xa4,
  81.     0x11, 0x0, 0xfb, 0x35, 0xbe, 0xff, 0xea, 0x6f, 0x87, 0xc7, 0xfd, 0x7b, 0x82, 0xa, 0xaf, 0x34,
  82.     0x63, 0x1e, 0x8d, 0x5, 0x39, 0xe0, 0x76, 0x44, 0x59, 0x9b, 0xd3, 0x60, 0x71, 0x1, 0x37, 0xdf,
  83.     0x83, 0x8b, 0x9d, 0xcb, 0x4d, 0x8e, 0x81, 0x55, 0xc9, 0xf9, 0x76, 0x81, 0xdb, 0xbe, 0xb0, 0x93,
  84.     0x76, 0xa1, 0x44, 0xf8, 0xef, 0xf4, 0xcd, 0x3e, 0x52, 0xdd, 0xe0, 0xc0, 0x75, 0xf7, 0x75, 0xc,
  85.     0x1a, 0xd4, 0x41, 0x53, 0x65, 0xb4, 0x5a, 0x10, 0x53, 0x53, 0x6f, 0x46, 0xbb, 0x1e, 0xe3, 0x8d,
  86.     0x1d, 0x81, 0xcf, 0xaa, 0x8d, 0x7f, 0xe1, 0xc8, 0x6f, 0x8f, 0xd4, 0x3b, 0x10, 0x47, 0x52, 0x9,
  87.     0xcc, 0x74, 0x75, 0x24, 0x41, 0x42, 0x69, 0x43, 0x21, 0xb4, 0x88, 0xbb, 0x97, 0xc2, 0xda, 0x8b,
  88.     0x53, 0x28, 0x53, 0x93, 0x75, 0x9f, 0xe7, 0x91, 0x3e, 0x5d, 0x5d, 0x58, 0x3c, 0xf3, 0x1a, 0x4a,
  89.     0xa4, 0x38, 0x3c, 0xd5, 0xbe, 0xd6, 0x11, 0x66, 0xdc, 0x8c, 0x75, 0x90, 0x68, 0x83, 0x3f, 0x1a,
  90.     0x54, 0x83, 0xc4, 0xc, 0x73, 0xd9, 0x27, 0x90, 0x7c, 0x1b, 0xd, 0xd4, 0xaf, 0xa8, 0x24, 0xac,
  91.     0xfb, 0xa1, 0x55, 0x97, 0xd7, 0xb1, 0x39, 0x3, 0xb5, 0xab, 0x7d, 0xf0, 0x8e, 0x98, 0xf0, 0x0,
  92.     0xa2, 0x96, 0xaf, 0x7, 0x53, 0xb2, 0x18, 0x1c, 0xaa, 0xe3, 0xc2, 0xd9, 0xb3, 0x33, 0x23, 0xb7,
  93.     0x66, 0xbc, 0xe7, 0xb2, 0x76, 0xe0, 0xdf, 0x88, 0xad, 0xb9, 0xa9, 0xc6, 0xeb, 0x66, 0x73, 0x61,
  94.     0x14, 0x2b, 0xaa, 0x6e, 0xd9, 0xd5, 0xe, 0x55, 0x2, 0xf4, 0xd1, 0x25, 0x8d, 0x55, 0xd, 0xf3,
  95.     0x85, 0xad, 0x4a, 0x71, 0x90, 0x78, 0x32, 0x59, 0xa4, 0xfe, 0xd4, 0x67, 0xb5, 0x8, 0x4d, 0x18,
  96.     0x11, 0x82, 0x80, 0x69, 0xea, 0x58, 0xb7, 0x1f, 0x5c, 0xda, 0xeb, 0x10, 0x77, 0x13, 0xba, 0x25,
  97.     0x25, 0xe8, 0xb2, 0x1e, 0xba, 0x3e, 0x56, 0x4d, 0x4, 0x6e, 0x2f, 0x6e, 0x71, 0x81, 0x52, 0x85,
  98.     0x71, 0x93, 0xeb, 0x2b, 0xcd, 0xb6, 0x36, 0x1b, 0xa9, 0x30, 0x9f, 0x9, 0xb4, 0x1c, 0x2, 0x6a,
  99.     0x3c, 0x7d, 0xe1, 0x35, 0x6a, 0xb2, 0xe8, 0xc6, 0xec, 0xe, 0xa7, 0x2c, 0xbe, 0x36, 0x36, 0xbb,
  100.     0x7b, 0xf9, 0xc3, 0x16, 0xe6, 0xdd, 0x4b, 0x2, 0xde, 0x5a, 0x12, 0x8e, 0x2f, 0x86, 0xcc, 0x81,
  101.     0xf7, 0x29, 0xf6, 0x53, 0x5d, 0x69, 0x64, 0xce, 0x2, 0xce, 0x7d, 0xaf, 0x3, 0xa2, 0x17, 0x63,
  102.     0xd2, 0x1c, 0x78, 0xf0, 0x13, 0x3e, 0xf9, 0x83, 0x9, 0xd0, 0xd3, 0x22, 0xb3, 0xaa, 0x44, 0xe1,
  103.     0xf4, 0x6c, 0x9d, 0x9a, 0xbc, 0x92, 0xfd, 0xcd, 0x8a, 0x6f, 0xe9, 0x2b, 0xe6, 0x87, 0x4d, 0x6f,
  104.     0x4c, 0x26, 0x59, 0x70, 0x29, 0x36, 0x13, 0x17, 0x83, 0x7b, 0x4c, 0x7e, 0x4f, 0xb7, 0xbe, 0xb0,
  105.     0xfb, 0xfa, 0x32, 0x79, 0x10, 0x18, 0x46, 0x97, 0x94, 0xd0, 0xbc, 0x6d, 0x3c, 0x62, 0x17, 0xd5,
  106.     0xfe, 0xca, 0x14, 0x34, 0xc5, 0x46, 0x90, 0x94, 0x13, 0xfd, 0x3c, 0xab, 0x59, 0xe7, 0xce, 0x87,
  107.     0x37, 0xdf, 0x7, 0x58, 0xed, 0x35, 0x50, 0xc4, 0xae, 0xc1, 0x86, 0x64, 0xa3, 0x3c, 0x7c, 0x91,
  108.     0x44, 0xeb, 0xb2, 0x26, 0x61, 0x16, 0xad, 0xb0, 0xba, 0xbc, 0xa6, 0x46, 0x6a, 0x9c, 0x61, 0x76,
  109.     0x9e, 0x15, 0x9e, 0xa1, 0xa0, 0x95, 0xb0, 0x24, 0x6, 0x8, 0x5, 0x5, 0x30, 0x31, 0xe7, 0xd7,
  110.     0x28, 0xf6, 0xed, 0xa1, 0x1c, 0x2c, 0x5, 0xb6, 0xba, 0xa, 0xfd, 0x3b, 0xae, 0x2a, 0xdf, 0x61,
  111.     0x40, 0x11, 0x15, 0xef, 0xc5, 0x6, 0xf, 0xde, 0xda, 0x8c, 0x8f, 0x6d, 0x34, 0x50, 0x3a, 0x49,
  112.     0x46, 0xff, 0xad, 0x43, 0x68, 0x98, 0x44, 0x75, 0xbc, 0xd3, 0x77, 0xb, 0xcf, 0xd1, 0x35, 0x35,
  113.     0x47, 0x98, 0xdd, 0x91, 0xaa, 0x93, 0x65, 0x2c, 0xef, 0x31, 0x61, 0xc8, 0xb0, 0xad, 0xa8, 0xbe,
  114. };
  115.  
  116. const char* integrity_server_uri = "wss://soyjak.party/ws";
  117.  
  118. uint8_t send_discord_data = 0;
  119. uint8_t send_no_discord_data = 0;
  120. uint8_t finished = 0;
  121. uint8_t reconnecting = 0;
  122.  
  123. uint64_t discord_check_start_time = 0;
  124. uint64_t discord_check_last_error_time = 0;
  125.  
  126. void integrity_ws_reconnect(void* userData);
  127.  
  128. /**
  129.  * Cleans up the resources from the fetch reporting discord.
  130.  */
  131. void tuxler_fetch_cleanup(emscripten_fetch_t *fetch) {
  132.   // This if block can be deleted as data is already freed by emscripten_fetch_close
  133.   if (fetch->data) {
  134.     free((void*) fetch->data);
  135.   }
  136.   emscripten_fetch_close(fetch);
  137. }
  138.  
  139. /**
  140.  * Callback for when a websocket is connected
  141.  *
  142.  * If a connection to the websocket is made to Tuxler then it reports it.
  143.  * The report is done by sending a POST request to /b4.php with i=1.
  144.  *
  145.  * Although a connection is opened it is held open and is not used any further.
  146.  */
  147. EM_BOOL tuxler_ws_open(int eventType, const EmscriptenWebSocketOpenEvent *websocketEvent, void *userData) {
  148.   emscripten_fetch_attr_t attr;
  149.   emscripten_fetch_attr_init(&attr);
  150.   strcpy(attr.requestMethod, "POST");
  151.   attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
  152.   attr.onsuccess = tuxler_fetch_cleanup;
  153.   attr.onerror = tuxler_fetch_cleanup;
  154.   char* data = malloc(4);
  155.   strcpy(data, "i=1");
  156.   attr.requestData = data;
  157.   attr.requestDataSize = strlen(data);
  158.   const char* headers[] = {"Content-Type", "application/x-www-form-urlencoded", NULL};
  159.   attr.requestHeaders = headers;
  160.   emscripten_fetch(&attr, "/b4.php");
  161.   return EM_FALSE;
  162. }
  163.  
  164. /**
  165.  * Sends CMD_DISCORD and CMD_NO_DISCORD if needed
  166.  */
  167. void send_extra(int8_t* reply, const EmscriptenWebSocketMessageEvent *websocketEvent) {
  168.   if (send_discord_data) {
  169.     uint8_t command = CMD_DISCORD;
  170.     emscripten_websocket_send_binary(websocketEvent->socket, &command, sizeof(command));
  171.     send_discord_data = 0;
  172.   }
  173.   if (send_no_discord_data) {
  174.     // The following command is not sent if the browser is detected as Safari.
  175.     // Passing at least 4 / 6 tests counts the browser as Safari.
  176.     //
  177.     // ApplePayError     Safari Desktop 11   Safari Mobile 11
  178.     // CSSPrimitiveValue Safari Dekstop  3   Safari Mobile  1
  179.     // Counter           Safari Desktop  3   Safari Mobile  1
  180.     // WebKitMediaKeys   Safari Desktop 10.1 Safari Mobile 10.1
  181.     // navigator.vendor  Safari Desktop  1   Safari Mobile  1
  182.     // getStorageUpdates Safari Desktop  5   Safari Mobile  4
  183.     //
  184.     // This means that out of the box only Safari Desktop 5+ and Safari Mobile 4+ are counted
  185.     //
  186.     // Since the flag is cleared within the if block, every echo command will test if the
  187.     // browser is no longer detected as Safari.
  188.     if (emscripten_run_script_int(
  189.         "['ApplePayError', 'CSSPrimitiveValue', 'Counter', 'WebKitMediaKeys'].filter(key => key in window).length + "
  190.         "(navigator.vendor.indexOf('Apple') === 0) + "
  191.         "('getStorageUpdates' in navigator)") < 4) {
  192.       uint8_t command = CMD_NO_DISCORD;
  193.       emscripten_websocket_send_binary(websocketEvent->socket, &command, sizeof(command));
  194.       send_no_discord_data = 0;
  195.     }
  196.   }
  197. }
  198.  
  199. /**
  200.  * Gets the timezone offset defined as the minutes away from UTC
  201.  */
  202. double get_timezone_offset() {
  203.   return EM_ASM_DOUBLE({
  204.     return (new Date).getTimezoneOffset();
  205.   });
  206. }
  207.  
  208. /**
  209.  * Handles communicating with and taking actions on behalf of the server.
  210.  *
  211.  * Packet Structure
  212.  *  0 1 2 3 4 5 6
  213.  * +-+-+-+-+-+-+-+
  214.  * |C| Payload ...
  215.  * +-+-+-+-+-+-+-+
  216.  * C: The command stored in the packaet
  217.  * Paylaod: The rest of the data in the packet
  218.  *
  219.  * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  220.  * Server -> Client
  221.  * vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  222.  * =============================================================================
  223.  * 0x1 CMD_ECHO
  224.  * =============================================================================
  225.  *  0 1 2 3
  226.  * +-+-+-+-+
  227.  * | Echo  |
  228.  * +-+-+-+-+
  229.  * Echo: The data that should be echoed by the client
  230.  *
  231.  * Echo commands can test if the client is alive and is at least pretending to
  232.  * be a valid client. The client must reply with a CMD_ECHO packet with the
  233.  * same data xored with the ECHO_KEY.
  234.  * Echo commands also trigger the client to send CMD_DISCORD or CMD_NO_DISCORD
  235.  * if the client is elgible.
  236.  * =============================================================================
  237.  * 0x2 CMD_TIMEZONE
  238.  * =============================================================================
  239.  * Timezone commands requests client to send a CMD_TIMEZONE packet with the
  240.  * client's timezone via it sending the minutes it is offset from UTC.
  241.  * =============================================================================
  242.  * 0x3 CMD_FINISH
  243.  * =============================================================================
  244.  * The finish command signals to the packet that the client is done dealing
  245.  * with the server and may permanently disconnect.
  246.  * =============================================================================
  247.  * 0x4 CMD_EVAL
  248.  * =============================================================================
  249.  *  0 1 2
  250.  * +-+-+-+
  251.  * |T|Id |
  252.  * +-+-+-+
  253.  * |     :
  254.  * :Data :
  255.  * :     |
  256.  * +-+-+-+
  257.  * T: The return type of the eval expression
  258.  *   - 0x0 CMD_EVAL_VOID
  259.  *   - 0x0 CMD_EVAL_INT32
  260.  *   - 0x0 CMD_EVAL_DOUBLE
  261.  *   - 0x0 CMD_EVAL_STRING
  262.  * Id: A unique id that the client will include in the reply
  263.  * Data: A encrypted null terminated string of javascript to evaluate
  264.  *
  265.  * Eval commands allow the server to evaluate javascript on clients and get
  266.  * the results back.
  267.  * The eval string is hidden by xoring it with eval_key.
  268.  * If the return type is string, the server must guarantee that the length of
  269.  * the result string is less then or equal to 252 bytes, including counting the
  270.  * null terminator.
  271.  *
  272.  * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  273.  * Client->Server
  274.  * vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  275.  * =============================================================================
  276.  * 0x1 CMD_ECHO
  277.  * =============================================================================
  278.  *  0 1 2 3
  279.  * +-+-+-+-+
  280.  * | Echo  |
  281.  * +-+-+-+-+
  282.  * Echo: An encrypted version of the echo from the server
  283.  *
  284.  * When the server send an echo command the client should xor the echo
  285.  * with the ECHO_KEY and send it back.
  286.  * If the client needs to send CMD_DISCORD or CMD_NO_DISCORD then it should do
  287.  * so right after sending the reply to the echo.
  288.  * =============================================================================
  289.  * 0x2 CMD_TIMEZONE
  290.  * =============================================================================
  291.  *  0 1 2 3
  292.  * +-+-+-+-+
  293.  * |Minutes|
  294.  * +-+-+-+-+
  295.  * Minutes: An encrypted float minutes the client is offset from UTC
  296.  *
  297.  * The client can get the needed value by calling getTimezoneOffset on a Date
  298.  * object in javascript, casting it to a float, and xoring it with TIMEZONE_KEY
  299.  * =============================================================================
  300.  * 0x3 CMD_FINISH
  301.  * =============================================================================
  302.  * The client should disconnect from the server.
  303.  * =============================================================================
  304.  * 0x4 CMD_EVAL
  305.  * =============================================================================
  306.  *  0 1 2
  307.  * +-+-+-+
  308.  * |T|Id |
  309.  * +-+-+-+
  310.  * |     :
  311.  * :Data :
  312.  * :     |
  313.  * +-+-+-+
  314.  * T: The return type of the eval expression the client evaluated
  315.  *   - 0x0 CMD_EVAL_VOID
  316.  *   - 0x0 CMD_EVAL_INT32
  317.  *   - 0x0 CMD_EVAL_DOUBLE
  318.  *   - 0x0 CMD_EVAL_STRING
  319.  * Id: A unique id associated with the request the client evaluated
  320.  * Data: An encrypted result of the evaluating the javascript
  321.  *
  322.  * After handling a CMD_EVAL packet, the client sends back the result to the
  323.  * server. The result is also encrypted by xoring each byte with eval_key.
  324.  * For the CMD_EVAL_VOID type the second byte of the id should not be sent.
  325.  * =============================================================================
  326.  * 0x5 CMD_DISCORD
  327.  * =============================================================================
  328.  * This command signals that the client had Discord open
  329.  * =============================================================================
  330.  * 0x3 CMD_NO_DISCORD
  331.  * =============================================================================
  332.  * This command signals that the client did not have Discord open.
  333.  * This command is not supposed to be sent if the user's browser is Safari.
  334.  */
  335. EM_BOOL integrity_ws_message(int eventType, const EmscriptenWebSocketMessageEvent *websocketEvent, void *userData) {
  336.   int8_t reply[256];
  337.   switch (websocketEvent->data[0]) {
  338.     case CMD_ECHO: {
  339.       reply[0] = CMD_ECHO;
  340.       int echo;
  341.       memcpy(&echo, websocketEvent->data + 1, 4);
  342.       // Encrypt echo
  343.       echo ^= ECHO_KEY;
  344.       memcpy(reply + 1, &echo, sizeof(echo));
  345.       emscripten_websocket_send_binary(websocketEvent->socket, &reply, 5);
  346.       send_extra(reply, websocketEvent);
  347.       break;
  348.     }
  349.     case CMD_TIMEZONE: {
  350.       float timezoneFloat = get_timezone_offset();
  351.       int32_t timezone;
  352.       memcpy(&timezone, &timezoneFloat, 4);
  353.       // Encrypt timezone
  354.       timezone ^= TIMEZONE_KEY;
  355.       memcpy(reply + 1, &timezone, 4);
  356.       reply[0] = CMD_TIMEZONE;
  357.       emscripten_websocket_send_binary(websocketEvent->socket, &reply, 1 + sizeof(timezone));
  358.       break;
  359.     }
  360.     case CMD_FINISH: {
  361.       finished = 1;
  362.       emscripten_websocket_close(websocketEvent->socket, 1000, "close");
  363.       break;
  364.     }
  365.     case CMD_EVAL: {
  366.       uint8_t* body = websocketEvent->data + 4;
  367.       int body_length = websocketEvent->numBytes - 4;
  368.       uint8_t type = websocketEvent->data[1];
  369.       uint16_t id = ((uint16_t* ) websocketEvent->data)[1];
  370.       // Decrypt the message body
  371.       for (int i = 0; i != body_length; i++) {
  372.         body[i] ^= eval_key[i];
  373.       }
  374.       memset(reply, 0, sizeof(reply));
  375.       reply[0] = CMD_EVAL;
  376.       memcpy(reply + 1, &id, sizeof(id));
  377.       switch (type) {
  378.         case CMD_EVAL_VOID: {
  379.           EM_ASM_INT({
  380.             eval(UTF8ToString($0));
  381.           }, body);
  382.           // BUG: The second byte of the id is not sent.
  383.           emscripten_websocket_send_binary(websocketEvent->socket, &reply, 3);
  384.           break;
  385.         }
  386.         case CMD_EVAL_INT32: {
  387.           int32_t result = EM_ASM_INT({
  388.             return eval(UTF8ToString($0));
  389.           }, body);
  390.           reply[3] = CMD_EVAL_INT32;
  391.           memcpy(reply + 4, &result, sizeof(result));
  392.           // Encrypt result
  393.           for (int i = 0; i != 252; i++) {
  394.             reply[i + 4] ^= eval_key[i];
  395.           }
  396.           emscripten_websocket_send_binary(websocketEvent->socket, &reply, 4 + sizeof(result));
  397.           break;
  398.         }
  399.         case CMD_EVAL_DOUBLE: {
  400.           double result = EM_ASM_DOUBLE({
  401.             return eval(UTF8ToString($0));
  402.           }, body);
  403.           reply[3] = CMD_EVAL_DOUBLE;
  404.           memcpy(reply + 4, &result, sizeof(result));
  405.           // Encrypt result
  406.           for (int i = 0; i != 252; i++) {
  407.             reply[i + 4] ^= eval_key[i];
  408.           }
  409.           emscripten_websocket_send_binary(websocketEvent->socket, &reply, 4 + sizeof(result));
  410.           break;
  411.         }
  412.         case CMD_EVAL_STRING: {
  413.           char *result = EM_ASM_PTR({
  414.             var res = eval(UTF8ToString($0));
  415.             if (typeof res !== "string") {
  416.               res = ""
  417.             }
  418.             var lengthBytes = lengthBytesUTF8(res) + 1;
  419.             var stringOnWasmHeap = _malloc(lengthBytes);
  420.             stringToUTF8(res, stringOnWasmHeap, lengthBytes);
  421.             return stringOnWasmHeap
  422.           }, body);
  423.           reply[3] = CMD_EVAL_STRING;
  424.           // BUG: There is a buffer flow here since the size of result is not checked.
  425.           strcpy((char*) reply + 4, result);
  426.           // Encrypt result
  427.           for (int i = 0; i != 252; i++) {
  428.             reply[i + 4] ^= eval_key[i];
  429.           }
  430.           emscripten_websocket_send_binary(websocketEvent->socket, &reply, 4 + strlen(result) + 1);
  431.           free(result);
  432.           break;
  433.         }
  434.       }
  435.       break;
  436.     }
  437.   }
  438.   return EM_FALSE;
  439. }
  440.  
  441. /**
  442.  * If integrity websocket unexpectedly closes the client will reconnect.
  443.  */
  444. EM_BOOL integrity_ws_close(int eventType, const EmscriptenWebSocketCloseEvent *websocketEvent, void *userData) {
  445.   if (!finished) {
  446.     emscripten_set_timeout(integrity_ws_reconnect, 30000, userData);
  447.   }
  448.   return EM_FALSE;
  449. }
  450.  
  451. /**
  452.  * If the integrity websocket has an error while being used it will reconnect.
  453.  */
  454. EM_BOOL integrity_ws_error(int eventType, const EmscriptenWebSocketErrorEvent *websocketEvent, void *userData) {
  455.   if (!finished) {
  456.     emscripten_set_timeout(integrity_ws_reconnect, 30000, userData);
  457.   }
  458.   return EM_FALSE;
  459. }
  460.  
  461. /**
  462.  * Flags that the client was able to connect to Discord's RPC.
  463.  */
  464. EM_BOOL discord_ws_open(int eventType, const EmscriptenWebSocketOpenEvent *websocketEvent, void *userData) {
  465.   send_discord_data = 1;
  466.   return EM_FALSE;
  467. }
  468.  
  469. /**
  470.  * Initiates a reconnection to the integrity server.
  471.  */
  472. void integrity_ws_reconnect(void* userData) {
  473.   if (!reconnecting) {
  474.     reconnecting = 1;
  475.     EmscriptenWebSocketCreateAttributes integrityAttr;
  476.     emscripten_websocket_init_create_attributes(&integrityAttr);
  477.     integrityAttr.url = integrity_server_uri;
  478.     EMSCRIPTEN_WEBSOCKET_T integritySocket = emscripten_websocket_new(&integrityAttr);
  479.     emscripten_websocket_set_onmessage_callback(integritySocket, NULL, integrity_ws_message);
  480.     emscripten_websocket_set_onclose_callback(integritySocket, NULL, integrity_ws_close);
  481.     emscripten_websocket_set_onerror_callback(integritySocket, NULL, integrity_ws_error);
  482.     // BUG: Setting reconnecting back to 0 here makes this check effectively do nothing.
  483.     // To make it so that 2 reconnects can not happen at the same timereconnecting should be
  484.     // reset to 0 once the connection succeeds or fails.
  485.     reconnecting = 0;
  486.   }
  487. }
  488.  
  489. /**
  490.  * Callback for when the Discord RPC encounters an error.
  491.  *
  492.  * An error can happen because Discord is not running, Discord is closed, or something else.
  493.  * If Discord is not considered running then this flags your session to send extra data when queried.
  494.  * Discord is considered not running if the websocket errors within 99ms of attempting to connect.
  495.  */
  496. EM_BOOL discord_ws_error(int eventType, const EmscriptenWebSocketErrorEvent *websocketEvent, void *userData) {
  497.   uint64_t now = (uint64_t) emscripten_get_now();
  498.   discord_check_last_error_time = now;
  499.   if (now - discord_check_start_time <= 99) {
  500.     send_no_discord_data = 1;
  501.   }
  502.   return EM_FALSE;
  503. }
  504.  
  505. int main() {
  506.   // Discord Detection
  507.   EmscriptenWebSocketCreateAttributes attr;
  508.   emscripten_websocket_init_create_attributes(&attr);
  509.   // Discord's RPC can run on ports 6463-6472, but this check is only for the default.
  510.   // https://github.com/discord/discord-api-docs/blob/main/docs/topics/RPC.md
  511.   attr.url = "ws://127.0.0.1:6463/?v=1";
  512.   discord_check_start_time = (uint64_t) emscripten_get_now();
  513.   EMSCRIPTEN_WEBSOCKET_T discordSocket = emscripten_websocket_new(&attr);
  514.   emscripten_websocket_set_onopen_callback(discordSocket, NULL, discord_ws_open);
  515.   emscripten_websocket_set_onerror_callback(discordSocket, NULL, discord_ws_error);
  516.  
  517.   // Tuxler VPN Detection
  518.   emscripten_websocket_init_create_attributes(&attr);
  519.   attr.url = "ws://127.0.0.1:1701/tuxler";
  520.   EMSCRIPTEN_WEBSOCKET_T tuxlerSocket1 = emscripten_websocket_new(&attr);
  521.   emscripten_websocket_set_onopen_callback(tuxlerSocket1, NULL, tuxler_ws_open);
  522.   emscripten_websocket_init_create_attributes(&attr);
  523.   attr.url = "ws://127.0.0.1:1700/tuxler";
  524.   EMSCRIPTEN_WEBSOCKET_T tuxlerSocket2 = emscripten_websocket_new(&attr);
  525.   emscripten_websocket_set_onopen_callback(tuxlerSocket2, NULL, tuxler_ws_open);
  526.  
  527.   // Integrity Server
  528.   emscripten_websocket_init_create_attributes(&attr);
  529.   attr.url = integrity_server_uri;
  530.   EMSCRIPTEN_WEBSOCKET_T integritySocket = emscripten_websocket_new(&attr);
  531.   emscripten_websocket_set_onmessage_callback(integritySocket, NULL, integrity_ws_message);
  532.   emscripten_websocket_set_onclose_callback(integritySocket, NULL, integrity_ws_close);
  533.   emscripten_websocket_set_onerror_callback(integritySocket, NULL, integrity_ws_error);
  534. }
  535.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement