Advertisement
Guest User

Untitled

a guest
Nov 19th, 2018
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.34 KB | None | 0 0
  1. // Compile with -O2 -std=c++17
  2. #include <algorithm>
  3. #include <array>
  4. #include <cassert>
  5. #include <cstdint>
  6. #include <cstring>
  7. #include <iomanip>
  8. #include <iostream>
  9. #include <variant>
  10. #include <string>
  11. #include <tuple>
  12. #include <vector>
  13. #include <random>
  14.  
  15. #include <sys/mman.h>
  16.  
  17. using u8 = uint8_t;
  18. using u16 = uint16_t;
  19. using u32 = uint32_t;
  20. using u64 = uint64_t;
  21.  
  22. using std::array;
  23. using std::cin;
  24. using std::cout;
  25. using std::endl;
  26. using std::get;
  27. using std::holds_alternative;
  28. using std::string;
  29. using std::tuple;
  30. using std::vector;
  31.  
  32. array<u8, 4> pack32(u32 val)
  33. {
  34.     return { u8(val), u8(val >> 8), u8(val >> 16), u8(val >> 24) };
  35. }
  36.  
  37. array<u8, 2> pack16(u16 val)
  38. {
  39.     return { u8(val & 0xFF), u8(val >> 8) };
  40. }
  41.  
  42. u16 unpack16(array<u8, 2> bytes)
  43. {
  44.     return bytes[0] + bytes[1] * 256;
  45. }
  46.  
  47. array<u8, 8> pack_4x16(u16 a, u16 b, u16 c, u16 d)
  48. {
  49.     array<u8, 8> res;
  50.     size_t pos = 0;
  51.     for (auto& x : { pack16(a), pack16(b), pack16(c), pack16(d) })
  52.     {
  53.         std::copy(x.begin(), x.end(), res.begin() + pos);
  54.         pos += 2;
  55.     }
  56.     return res;
  57. }
  58.  
  59. std::tuple<u16, u16, u16, u16> unpack_4x16(const array<u8, 8>& in)
  60. {
  61.     return std::make_tuple(unpack16({ in[0], in[1] }),
  62.                            unpack16({ in[2], in[3] }),
  63.                            unpack16({ in[4], in[5] }),
  64.                            unpack16({ in[6], in[7] }));
  65. }
  66.  
  67. u8 rol8(u8 x, int shift)
  68. {
  69.     shift %= 8;
  70.     return ((x << shift) & 0xFF) | (x >> (8 - shift));
  71. }
  72.  
  73. u8 ror8(u8 x, int shift)
  74. {
  75.     return rol8(x, 8 - (shift % 8));
  76. }
  77.  
  78. array<u8, 8> xor8(const array<u8, 8>& a, const array<u8, 8>& b)
  79. {
  80.     array<u8, 8> res;
  81.     for (int i = 0; i < 8; i++)
  82.         res[i] = a[i] ^ b[i];
  83.     return res;
  84. }
  85.  
  86. struct round_key
  87. {
  88.     u16 a, b;
  89.     array<u8, 4> shuffle;
  90. };
  91.  
  92. struct key
  93. {
  94.     array<u8, 256> xorbox;
  95.     array<round_key, 16> round_keys;
  96.  
  97.     key(const array<u8, 256> k1, const array<u8, 128> k2)
  98.     {
  99.         xorbox = k1;
  100.         for (int i = 0; i < 16; i++)
  101.         {
  102.             auto k2_it = &k2[i * sizeof(round_key)];
  103.             round_keys[i].a = unpack16({ *(k2_it + 0), *(k2_it + 1) });
  104.             round_keys[i].b = unpack16({ *(k2_it + 2), *(k2_it + 3) });
  105.             memcpy(&round_keys[i].shuffle, k2_it + 4, 4);
  106.         }
  107.     }
  108. };
  109.  
  110. std::tuple<u16, u16, u16, u16> tsb_cipher_round(u16 a, u16 b, u16 c, u16 d,
  111.                                                 const array<u8, 256> xorbox,
  112.                                                 const array<u8, 4> shuffle)
  113. {
  114.     array<u8, 8> block = pack_4x16(a, b, c, d);
  115.     u8 x1 = rol8(xorbox[shuffle[1] ^ block[1] ^ block[3] ^ block[5] ^ block[7]], 3);
  116.     u8 x2 = rol8(xorbox[shuffle[0] ^ x1 ^ block[0] ^ block[2]], 1);
  117.     u8 x3 = ror8(xorbox[shuffle[2] ^ block[0] ^ block[2] ^ block[4] ^ block[6]], 3);
  118.     u8 x4 = ror8(xorbox[shuffle[3] ^ x3 ^ block[5] ^ block[7]], 1);
  119.     array<u8, 8> xors = { x1, x4, x1, x4, x2, x3, x2, x3 };
  120.     for (int i = 0; i < 8; i++)
  121.         block[i] ^= xors[i];
  122.     return unpack_4x16(block);
  123. }
  124.  
  125. array<u8, 8> tsb_encrypt_block(const array<u8, 8>& in, const key& k)
  126. {
  127.     u16 a, b, c, d;
  128.     std::tie(a, b, c, d) = unpack_4x16(in);
  129.  
  130.     for (const round_key& round_key : k.round_keys)
  131.     {
  132.         std::tie(a, b, c, d) = std::make_tuple(d, a, b, c);
  133.         b += round_key.a;
  134.         d += round_key.b;
  135.         std::tie(a, b, c, d) = tsb_cipher_round(a, b, c, d, k.xorbox, round_key.shuffle);
  136.     }
  137.     return pack_4x16(d, a, b, c);
  138. }
  139.  
  140. array<u8, 8> tsb_decrypt_block(const array<u8, 8>& in, const key& k)
  141. {
  142.     u16 a, b, c, d;
  143.     std::tie(a, b, c, d) = unpack_4x16(in);
  144.  
  145.     for (int i = k.round_keys.size() - 1; i >= 0; i--)
  146.     {
  147.         const round_key& round_key = k.round_keys[i];
  148.         std::tie(a, b, c, d) = std::make_tuple(b, c, d, a);
  149.         std::tie(a, b, c, d) = tsb_cipher_round(a, b, c, d, k.xorbox, round_key.shuffle);
  150.         b -= round_key.a;
  151.         d -= round_key.b;
  152.     }
  153.     return pack_4x16(b, c, d, a);
  154. }
  155.  
  156. array<u8, 8> cbc_mac(vector<u8> data, const key& key)
  157. {
  158.     // Add padding
  159.     u8 pad = 8 - data.size() % 8;
  160.     for (int i = 0; i < pad; i++)
  161.         data.push_back(pad);
  162.     // Calculate tag
  163.     array<u8, 8> res = {};
  164.     for (size_t i = 0; i < data.size(); i += 8)
  165.     {
  166.         array<u8, 8> block;
  167.         std::copy_n(data.begin() + i, 8, block.begin());
  168.         res = xor8(res, block);
  169.         res = tsb_encrypt_block(res, key);
  170.     }
  171.     return res;
  172. }
  173.  
  174. int nibble_to_int(char nibble)
  175. {
  176.     if (isdigit(nibble))
  177.         return nibble - '0';
  178.     if (isupper(nibble))
  179.         return nibble - 'A' + 10;
  180.     if (islower(nibble))
  181.         return nibble - 'a' + 10;
  182.     return -1;
  183. }
  184.  
  185. vector<u8> read_from_hex()
  186. {
  187.     vector<u8> res;
  188.     string hex;
  189.     std::getline(cin, hex);
  190.     for (size_t i = 0; i < hex.size(); i += 2)
  191.     {
  192.         int a = nibble_to_int(hex[i]);
  193.         int b = nibble_to_int(hex[i + 1]);
  194.         if (a == -1 || b == -1)
  195.             break;
  196.         res.push_back(a * 16 + b);
  197.     }
  198.     return res;
  199. }
  200.  
  201. void compile(const key& key)
  202. {
  203.     // Only basic operations for now, we'll add more in the next version.
  204.     // Example: 100+5^123
  205.     cout << "Expression: " << std::flush;
  206.     string expr;
  207.     bool ok = false;
  208.     while (!ok)
  209.     {
  210.         std::getline(cin, expr);
  211.         if (std::any_of(expr.begin(), expr.end(), [](char x) {return !isspace(x); }))
  212.             ok = true;
  213.     }
  214.  
  215.     std::vector<std::variant<char, u32>> tokens;
  216.     for (char ch : expr)
  217.     {
  218.         if (isspace(ch))
  219.             continue;
  220.         if (isdigit(ch))
  221.         {
  222.             if (!tokens.size() || holds_alternative<char>(tokens.back()))
  223.                 tokens.push_back(u32(0));
  224.             auto& val = get<u32>(tokens.back());
  225.             val *= 10;
  226.             val += ch - '0';
  227.         }
  228.         else if (tokens.size() && holds_alternative<u32>(tokens.back()) && ch == '+')
  229.         {
  230.             tokens.push_back('+');
  231.         }
  232.         else if (tokens.size() && holds_alternative<u32>(tokens.back()) && ch == '^')
  233.         {
  234.             tokens.push_back('^');
  235.         }
  236.         else
  237.         {
  238.             cout << "Invalid expression!" << endl;
  239.             return;
  240.         }
  241.     }
  242.     if (!tokens.size() || holds_alternative<char>(tokens.back()))
  243.     {
  244.         cout << "Invalid expression!" << endl;
  245.         return;
  246.     }
  247.  
  248.     vector<u8> code;
  249.    
  250.     // mov eax, imm32
  251.     code.push_back(0xB8);
  252.     for (u8 x : pack32(get<u32>(tokens[0])))
  253.         code.push_back(x);
  254.  
  255.     for (size_t i = 1; i < tokens.size(); i += 2)
  256.     {
  257.         auto op = get<char>(tokens[i]);
  258.         auto arg = get<u32>(tokens[i + 1]);
  259.         if (op == '+')
  260.         {
  261.             // add eax, imm32
  262.             code.push_back(0x48);
  263.             code.push_back(0x05);
  264.         }
  265.         else
  266.         {
  267.             // xor eax, imm32
  268.             assert(op == '^');
  269.             code.push_back(0x35);
  270.         }
  271.         for (u8 x : pack32(arg))
  272.             code.push_back(x);
  273.     }
  274.     // ret
  275.     code.push_back(0xC3);
  276.  
  277.     auto tag = cbc_mac(code, key);
  278.  
  279.     cout << "Code: ";
  280.     for (u8 byte : code)
  281.         cout << std::hex << std::setw(2) << std::setfill('0') << (u32)byte;
  282.     cout << endl;
  283.  
  284.     cout << "Tag: ";
  285.     for (u8 byte : tag)
  286.         cout << std::hex << std::setw(2) << std::setfill('0') << (u32)byte;
  287.     cout << std::dec;
  288.     cout << endl;
  289. }
  290.  
  291. u32 call_shellcode(vector<u8> shellcode)
  292. {
  293.     u8* payload_addr = (u8*)mmap(nullptr, shellcode.size(), PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  294.     if (payload_addr == (u8*)-1)
  295.     {
  296.         cout << "mmap() failed, please contact admin" << endl;
  297.         return -1;
  298.     }
  299.     std::copy(shellcode.begin(), shellcode.end(), payload_addr);
  300.     u32 (*payload)();
  301.     payload = (decltype(payload))payload_addr;
  302.     return payload();
  303. }
  304.  
  305. void test(const key& key)
  306. {
  307.     cout << "Code: " << std::flush;
  308.     vector<u8> code = read_from_hex();
  309.     cout << "Tag: " << std::flush;
  310.     vector<u8> tag = read_from_hex();
  311.     auto correct_tag = cbc_mac(code, key);
  312.     if (tag.size() != 8 || !std::equal(tag.begin(), tag.end(), correct_tag.begin()))
  313.     {
  314.         cout << "Incorrect tag!" << std::endl;
  315.         return;
  316.     }
  317.     // Execute the payload
  318.     u32 ret = call_shellcode(code);
  319.     cout << "Result: " << ret << endl;
  320. }
  321.  
  322. int main()
  323. {
  324.     std::ios_base::sync_with_stdio(false);
  325.  
  326.     // Self-test
  327.     array<u8, 256> test_key_a = { 172, 195, 40, 161, 104, 150, 205, 114, 247, 221, 247, 142, 209, 54, 148, 145, 246, 94, 218, 142, 122, 169, 22, 200, 145, 246, 196, 251, 52, 248, 56, 255, 49, 228, 71, 217, 51, 26, 164, 194, 166, 143, 113, 179, 15, 136, 235, 40, 231, 123, 231, 141, 176, 40, 79, 12, 3, 204, 182, 111, 90, 74, 195, 81, 83, 35, 101, 30, 58, 36, 28, 165, 193, 140, 99, 13, 64, 129, 128, 84, 133, 139, 127, 169, 126, 77, 132, 140, 69, 209, 222, 243, 216, 47, 0, 145, 1, 235, 240, 206, 160, 230, 224, 32, 134, 13, 126, 177, 171, 43, 172, 173, 202, 169, 198, 199, 185, 93, 176, 187, 175, 242, 200, 202, 178, 27, 152, 114, 230, 248, 125, 58, 206, 142, 175, 16, 1, 230, 4, 210, 23, 197, 250, 13, 62, 33, 68, 211, 89, 108, 138, 208, 236, 23, 77, 71, 130, 248, 129, 197, 86, 230, 99, 58, 148, 30, 178, 19, 244, 79, 73, 87, 91, 153, 86, 40, 29, 125, 66, 222, 193, 66, 223, 61, 84, 225, 35, 67, 251, 72, 79, 224, 248, 0, 59, 216, 254, 147, 170, 243, 212, 216, 6, 23, 207, 51, 15, 57, 203, 95, 61, 240, 166, 220, 38, 156, 158, 244, 208, 87, 1, 204, 155, 66, 32, 207, 49, 115, 202, 162, 244, 227, 66, 169, 171, 216, 221, 130, 167, 174, 51, 63, 157, 225, 150, 179, 113, 27, 45, 74, 196, 215, 83, 20, 150, 180 };
  328.     array<u8, 128> test_key_b = { 105, 244, 227, 54, 185, 151, 105, 32, 128, 75, 254, 45, 128, 138, 96, 62, 8, 58, 178, 48, 205, 245, 77, 242, 113, 177, 220, 243, 55, 196, 28, 121, 162, 29, 26, 150, 185, 13, 31, 220, 52, 6, 37, 5, 126, 184, 81, 180, 166, 106, 86, 111, 191, 207, 107, 240, 29, 188, 134, 89, 208, 242, 142, 227, 232, 226, 204, 124, 189, 154, 146, 187, 4, 122, 16, 151, 120, 9, 105, 150, 77, 56, 255, 75, 53, 219, 163, 36, 95, 111, 106, 161, 108, 191, 80, 35, 164, 196, 224, 243, 110, 61, 111, 229, 247, 248, 64, 14, 250, 106, 67, 254, 65, 39, 212, 190, 200, 136, 176, 77, 182, 45, 17, 173, 74, 201, 122, 113 };
  329.     array<u8, 8> test_ct = { 48, 49, 50, 51, 52, 53, 54, 55 };
  330.     array<u8, 8> test_pt = { 0x08, 0x11, 0x84, 0xe3, 0xd8, 0x06, 0xc1, 0x56 };
  331.     array<u8, 8> test_out = tsb_decrypt_block(test_ct, key{ test_key_a, test_key_b });
  332.     assert(test_out == test_pt);
  333.     test_out = tsb_encrypt_block(test_pt, key{ test_key_a, test_key_b });
  334.     assert(test_out == test_ct);
  335.  
  336.     // Initialization
  337.     std::random_device rd;
  338.     array<u8, 256> main_key_a;
  339.     array<u8, 128> main_key_b;
  340.     for (auto& byte : main_key_a)
  341.         byte = rd();
  342.     for (auto& byte : main_key_b)
  343.         byte = rd();
  344.     key main_key { main_key_a, main_key_b };
  345.  
  346.     cout << "Welcome to our expression compiler!" << endl;
  347.  
  348.     // Menu
  349.     while (1)
  350.     {
  351.         cout << "1. Compile an expression" << endl;
  352.         cout << "2. Test the result" << endl;
  353.         cout << "3. Exit" << endl;
  354.         string opt;
  355.         std::getline(cin, opt);
  356.         if (opt == "1")
  357.             compile(main_key);
  358.         else if (opt == "2")
  359.             test(main_key);
  360.         else if (opt == "3")
  361.             break;
  362.         else
  363.             cout << "Invalid option!" << endl;
  364.     }
  365. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement