// File: /workspace/github_cpp_makefile_star2_O1/cgvwzq[P]aes_bf/src/aes-brute-force.cpp
// Function: main
int main (int argc, char*argv[]) 
{
	uint8_t payload[16] = {0};
	uint8_t key[16] = {0};
	uint8_t iv[16] = {0};
	uint8_t plain_mask[16] = {0};
	uint8_t plain[16] = {0};
	uint8_t next_block[16] = {0};
	uint8_t cipher_mask[16] = {0};
	uint8_t cipher[16] = {0};

	const char *payload_str = "4D346731_435F6330_306B3133_5F465457"; // payload

	const char *key_str = "FD621FE5_A2B40253_9DFA147C_A9272778"; //  fixed on Linux 

	#ifndef PADDING
		const char *iv_str = "20202020_20202020_20202020_20202020"; // fixed on Chrome
		const char *plain_mask_str = "A0A0A0A0_A0A0A0A0_A0A0A0A0_A0A0A0A0A0"; // bit mask for valid chars
		const char *plain_str = "20202020_20202020_20202020_20202020"; // valid ascii chars
	#else
		const char *iv_str = "7B007D00_2A007B00_2D002D00_3A002800";
		const char *plain_mask_str = "A0A0A0A0_A0A0A0A0_A0A0A0A0_A0A0A0A0FF"; // bit mask for valid chars + padding
		const char *plain_str = "20202020_20202020_20202020_20202001"; // valid ascii chars + padding
	#endif

	const char *cipher_mask_str = "FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF"; // try all chars
	const char *cipher_str = "00000000_00000000_00000000_00000000"; 
	const char *next_block_str = "00000000_00000000_00000000_00000000"; 

	char buf[8][1024] = {0};

	memcpy (buf[0], payload_str, MIN(strlen (payload_str), 1024));
	memcpy (buf[1], key_str, MIN(strlen (key_str), 1024));
	memcpy (buf[2], iv_str, MIN(strlen (iv_str), 1024));
	memcpy (buf[3], plain_mask_str, MIN(strlen (plain_mask_str), 1024));
	memcpy (buf[4], plain_str, MIN(strlen (plain_str), 1024));
	memcpy (buf[5], next_block_str, MIN(strlen (next_block_str), 1024));
	memcpy (buf[6], cipher_mask_str, MIN(strlen (cipher_mask_str), 1024));
	memcpy (buf[7], cipher_str, MIN(strlen (cipher_str), 1024));

	if (0 != aes128_self_test())
	{
		std::cerr << "ERROR: AES-NI self test failed" << std::endl;
		exit(-1);
    }

    unsigned int len;
    len = user_hexstr_to_bytes (payload, 16, buf[0], strlen (buf[0]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (key, 16, buf[1], strlen (buf[1]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (iv, 16, buf[2], strlen (buf[2]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (plain_mask, 16, buf[3], strlen (buf[3]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (plain, 16, buf[4], strlen (buf[4]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (next_block, 16, buf[5], strlen (buf[5]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (cipher_mask, 16, buf[6], strlen (buf[6]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (cipher, 16, buf[7], strlen (buf[7]) + 1);
	assert (16 == len);

	__m128i key_schedule[20] = {0};
	aes128_load_key (key, key_schedule);
	#ifndef PADDING
		aes128_dec (key_schedule, payload, next_block); 
	#endif

	unsigned int n_threads = std::thread::hardware_concurrency ();
	//if (0 == n_threads)
	if (true) // debug
	{
		n_threads = 1;
	}

	std::cout << "[+] INFO: " << n_threads << " concurrent threads supported in hardware." << std::endl << std::endl;
	std::cout << "[+] Search parameters:\t" << std::endl << std::endl;
	std::cout << "\t- n_threads:\t" << n_threads << std::endl;
	println_128 ("\t- payload:\t", payload);
	println_128 ("\t- key:\t\t", key);
	println_128 ("\t- iv:\t\t", iv);
    println_128 ("\t- plain_mask:\t", plain_mask);
    println_128 ("\t- plain:\t", plain);
	#ifndef PADDING
		// start from valid ciphertext
		aes_brute_force::initial_ciphertext (cipher, next_block);
	#endif
    println_128 ("\t- cipher:\t", cipher);
    println_128 ("\t- next_block:\t", next_block);
	std::cout << std::endl;

	std::cout << "[+] Dividing work in jobs..." << std::endl << std::endl;
	voffset_t v;
	aes_brute_force::mask_to_offsets (cipher_mask, next_block, &v);
	uint8_t jobs_cipher_mask[16];
	memcpy (jobs_cipher_mask, cipher_mask, 16);

	if (1 == v.n_offsets)
	{
		n_threads = 1;
		std::cout << "[+] INFO: n_threads set to 1 because n_offsets=1" << std::endl;
	}
	if (1 != n_threads)
	{
		jobs_cipher_mask[v.offsets[0]] = 0; //fix this key byte at the job level.
	}
	std::vector<std::thread *> threads (n_threads);
	std::vector<aes_brute_force *> jobs (n_threads);
	aes_brute_force::reset ();

	int n_ciphers_per_thread = (n_threads == 1) ? 0 : ((v.n_valid_chars + n_threads - 1) / n_threads);
	unsigned int nbits = 0;
	for (unsigned int i=v.n_valid_chars; i; i = i >> 1, nbits++);

	unsigned int jobs_cnt = 0;
	for (unsigned int thread_i=0; thread_i < n_threads; thread_i++)
	{
		cipher[v.offsets[0]] = v.valid_chars[0][jobs_cnt++];
		jobs.at(thread_i) = new aes_brute_force (jobs_cipher_mask, cipher, key, iv, plain_mask, plain, next_block);
		printf ("\tthread_%d: %d jobs ", thread_i, n_ciphers_per_thread);
		print_128 ("(mask : ", jobs_cipher_mask, ")\n");
		for (int i=0; i < n_ciphers_per_thread-1; i++)
		{
			cipher[v.offsets[0]] = v.valid_chars[0][jobs_cnt++];
			jobs.at(thread_i)->push(cipher);
		}
	}
	// TODO: calculate entropy from given masks
	std::cout  << std::endl << "\tlaunching " << (v.n_offsets * nbits) << " bits search" << std::endl;
	std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
	for (unsigned int thread_i=0; thread_i < n_threads; thread_i++)
	{
		threads.at(thread_i) = new std::thread(&aes_brute_force::compute, jobs.at(thread_i));
	}

	bool found = false;
	uint64_t loop_cnt = 0;
	int winner = -1;
	for (unsigned int thread_i=0; thread_i < n_threads; thread_i++)
	{
		threads.at(thread_i)->join();
		if (jobs.at(thread_i)->found)
		{
			found = true;
			winner = thread_i;
			memcpy (cipher, jobs.at(thread_i)->valid_cipher, 16);

		}
		loop_cnt += jobs.at(thread_i)->loop_cnt;
	}
	std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
	std::cout << std::endl;
	if (found)
	{
		std::cout << "[+] Thread " << winner << " claims to have found a valid ciphertext" << std::endl;
        println_128 ("[+] CIPHER FOUND: ", cipher);
    }
	else
	{
        std::cout << "[!] No valid cipher could be found." << std::endl;
    }
	std::cout << std::endl << "[+] Performances:" << std::endl;
    std::cout << "\t" << std::dec << loop_cnt << " AES128 operations done in ";
    std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
    std::cout << time_span.count() << "s" << std::endl;

	if (!loop_cnt)
	{
		return 1;
	}

    uint64_t ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t2-t1).count();
    unsigned int aes_op_duration_ns = ns / loop_cnt;

    std::cout << "\t" << aes_op_duration_ns << " ns per AES128 operation" <<std::endl;
    uint64_t ciphers_per_sec = loop_cnt / time_span.count();
	if (ciphers_per_sec > 1000000)
	{
		std::cout << "\t" << std::fixed << std::setprecision(2) << ciphers_per_sec/1000000.0 << " million ciphers per second" << std::endl;
	}
	else
	{
		std::cout << "\t" << ciphers_per_sec << " cipers per second" << std::endl;
	}
	if (found)
	{
		uint8_t dec[16] = {0};
		char txt[17] = {0}; 
		__m128i key_schedule[20] = {0};
		aes128_load_key (key, key_schedule);
		aes128_dec (key_schedule, cipher, dec); 
		for (unsigned int i=0; i < 16; i++) {
			dec[i] ^= iv[i]; // IV
		}
		memcpy (txt, dec, 16);
		println_128 ("[+] Ciphertext: ", cipher);
		println_128 ("[+] Plaintext: ", dec);
		printf("\tascii: %s (length=%zu)\n", txt, strlen(txt));
		#ifndef PADDING
			char txt2[17] = {0};
			println_128 ("[+] Next block: ", next_block);
			for (unsigned int i=0; i < 16; i++) {
				next_block[i] ^= cipher[i]; 
			}
			memcpy (txt2, next_block, 16);
			println_128 ("[+] Next block XOR cipher: ", next_block);
			printf("\tascii: %s (length=%zu)\n", txt2, strlen(txt2));
		#endif
	}

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x3268, %rsp           # imm = 0x3268
vxorps %xmm0, %xmm0, %xmm0
vmovaps %xmm0, 0xb0(%rsp)
vmovaps %xmm0, 0x40(%rsp)
vmovaps %xmm0, 0x30(%rsp)
vmovaps %xmm0, 0x50(%rsp)
vmovaps %xmm0, 0xa0(%rsp)
vmovaps %xmm0, 0x90(%rsp)
vmovaps %xmm0, 0x80(%rsp)
vmovaps %xmm0, 0x10(%rsp)
leaq 0x1283(%rsp), %rbx
movl $0x1fdd, %edx           # imm = 0x1FDD
movq %rbx, %rdi
xorl %esi, %esi
callq 0x20b0
vmovups 0x29ef(%rip), %ymm0     # 0x5085
vmovups %ymm0, -0x23(%rbx)
movl $0x37353435, -0x4(%rbx) # imm = 0x37353435
vmovups 0x29ff(%rip), %ymm0     # 0x50a9
vmovups %ymm0, 0x3dd(%rbx)
movl $0x38373732, 0x3fc(%rbx) # imm = 0x38373732
vmovups 0x2a09(%rip), %ymm0     # 0x50cd
vmovups %ymm0, 0x7dd(%rbx)
movl $0x30303832, 0x7fc(%rbx) # imm = 0x30303832
movabsq $0x4646304130413041, %rax # imm = 0x4646304130413041
movq %rax, 0xbfa(%rbx)
vmovups 0x2a02(%rip), %ymm0     # 0x50f1
vmovups %ymm0, 0xbdd(%rbx)
vmovups 0x2a18(%rip), %ymm0     # 0x5117
vmovups %ymm0, 0xfdd(%rbx)
movl $0x31303032, 0xffc(%rbx) # imm = 0x31303032
movl $0x30303030, %eax       # imm = 0x30303030
movl %eax, 0x13fc(%rbx)
vmovups 0x2a3b(%rip), %ymm0     # 0x515f
vmovups %ymm0, 0x13dd(%rbx)
vmovups 0x2a07(%rip), %ymm1     # 0x513b
vmovups %ymm1, 0x17dd(%rbx)
movl $0x46464646, 0x17fc(%rbx) # imm = 0x46464646
movl %eax, 0x1bfc(%rbx)
vmovups %ymm0, 0x1bdd(%rbx)
leaq 0x28e5(%rip), %rdi      # 0x5040
leaq 0x230(%rsp), %rbx
movq %rbx, %rsi
vzeroupper
callq 0x35c5
vmovdqa 0x289a(%rip), %xmm0     # 0x5010
vmovdqa (%rbx), %xmm1
vmovdqa 0xa0(%rbx), %xmm2
vpxor %xmm0, %xmm1, %xmm3
vaesenc 0x10(%rbx), %xmm3, %xmm3
vaesenc 0x20(%rbx), %xmm3, %xmm3
vaesenc 0x30(%rbx), %xmm3, %xmm3
vaesenc 0x40(%rbx), %xmm3, %xmm3
vaesenc 0x50(%rbx), %xmm3, %xmm3
vaesenc 0x60(%rbx), %xmm3, %xmm3
vaesenc 0x70(%rbx), %xmm3, %xmm3
vaesenc 0x80(%rbx), %xmm3, %xmm3
vaesenc 0x90(%rbx), %xmm3, %xmm3
vaesenclast %xmm2, %xmm3, %xmm3
vmovdqa %xmm3, 0xf0(%rsp)
vmovdqa 0x2848(%rip), %xmm3     # 0x5020
vpxor %xmm3, %xmm2, %xmm2
vaesdec 0xb0(%rbx), %xmm2, %xmm2
vaesdec 0xc0(%rbx), %xmm2, %xmm2
vaesdec 0xd0(%rbx), %xmm2, %xmm2
vaesdec 0xe0(%rbx), %xmm2, %xmm2
vaesdec 0xf0(%rbx), %xmm2, %xmm2
vaesdec 0x100(%rbx), %xmm2, %xmm2
vaesdec 0x110(%rbx), %xmm2, %xmm2
vaesdec 0x120(%rbx), %xmm2, %xmm2
vaesdec 0x130(%rbx), %xmm2, %xmm2
vaesdeclast %xmm1, %xmm2, %xmm1
vmovdqa %xmm1, 0xc0(%rsp)
vmovq 0xf8(%rsp), %xmm1
vmovq 0xf0(%rsp), %xmm2
vpunpcklqdq %xmm1, %xmm2, %xmm1 # xmm1 = xmm2[0],xmm1[0]
vpxor %xmm3, %xmm1, %xmm1
vpternlogq $0xf6, 0xc0(%rsp), %xmm0, %xmm1
vptest %xmm1, %xmm1
jne 0x3463
leaq 0x1260(%rsp), %r14
movq %r14, %rdi
callq 0x2070
leaq 0x1(%rax), %rcx
movq %r14, %rdi
movq %rcx, %rsi
movq %r14, %rdx
callq 0x24c3
shrq %rax
cmpq $0x10, %rax
movl $0x10, %ebx
cmovaeq %rbx, %rax
leaq 0xb0(%rsp), %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x23d5
cmpl $0x10, %eax
jne 0x3488
leaq 0x1660(%rsp), %r14
movq %r14, %rdi
callq 0x2070
leaq 0x1(%rax), %rcx
movq %r14, %rdi
movq %rcx, %rsi
movq %r14, %rdx
callq 0x24c3
shrq %rax
cmpq $0x10, %rax
cmovbq %rax, %rbx
leaq 0x40(%rsp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x23d5
cmpl $0x10, %eax
jne 0x34a7
leaq 0x1a60(%rsp), %r14
movq %r14, %rdi
callq 0x2070
leaq 0x1(%rax), %rcx
movq %r14, %rdi
movq %rcx, %rsi
movq %r14, %rdx
callq 0x24c3
shrq %rax
cmpq $0x10, %rax
movl $0x10, %ebx
cmovaeq %rbx, %rax
leaq 0x30(%rsp), %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x23d5
cmpl $0x10, %eax
jne 0x34c6
leaq 0x1e60(%rsp), %r14
movq %r14, %rdi
callq 0x2070
leaq 0x1(%rax), %rcx
movq %r14, %rdi
movq %rcx, %rsi
movq %r14, %rdx
callq 0x24c3
shrq %rax
cmpq $0x10, %rax
cmovbq %rax, %rbx
leaq 0x50(%rsp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x23d5
cmpl $0x10, %eax
jne 0x34e5
leaq 0x2260(%rsp), %r14
movq %r14, %rdi
callq 0x2070
leaq 0x1(%rax), %rcx
movq %r14, %rdi
movq %rcx, %rsi
movq %r14, %rdx
callq 0x24c3
shrq %rax
cmpq $0x10, %rax
movl $0x10, %ebx
cmovaeq %rbx, %rax
leaq 0xa0(%rsp), %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x23d5
cmpl $0x10, %eax
jne 0x3504
leaq 0x2660(%rsp), %r14
movq %r14, %rdi
callq 0x2070
leaq 0x1(%rax), %rcx
movq %r14, %rdi
movq %rcx, %rsi
movq %r14, %rdx
callq 0x24c3
shrq %rax
cmpq $0x10, %rax
cmovbq %rax, %rbx
leaq 0x90(%rsp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x23d5
cmpl $0x10, %eax
jne 0x3523
leaq 0x2a60(%rsp), %r14
movq %r14, %rdi
callq 0x2070
leaq 0x1(%rax), %rcx
movq %r14, %rdi
movq %rcx, %rsi
movq %r14, %rdx
callq 0x24c3
shrq %rax
cmpq $0x10, %rax
movl $0x10, %ebx
cmovaeq %rbx, %rax
leaq 0x80(%rsp), %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x23d5
cmpl $0x10, %eax
jne 0x3542
leaq 0x2e60(%rsp), %r14
movq %r14, %rdi
callq 0x2070
leaq 0x1(%rax), %rcx
movq %r14, %rdi
movq %rcx, %rsi
movq %r14, %rdx
callq 0x24c3
shrq %rax
cmpq $0x10, %rax
cmovbq %rax, %rbx
leaq 0x10(%rsp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x23d5
cmpl $0x10, %eax
jne 0x3561
callq 0x21a0
movq 0x450b(%rip), %r15      # 0x6fd0
leaq 0x270f(%rip), %rsi      # 0x51db
movl $0xa, %edx
movq %r15, %rdi
callq 0x2170
movl $0x1, %esi
movq %r15, %rdi
callq 0x20d0
movq %rax, %rbx
leaq 0x26f6(%rip), %rsi      # 0x51e6
movl $0x2a, %edx
movq %rax, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
leaq 0x26bc(%rip), %rsi      # 0x5211
movl $0x17, %edx
movq %r15, %rdi
callq 0x2170
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
leaq 0x266f(%rip), %rsi      # 0x5229
movl $0xe, %edx
movq %r15, %rdi
callq 0x2170
movl $0x1, %esi
movq %r15, %rdi
callq 0x20d0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
leaq 0x2633(%rip), %rdi      # 0x5238
leaq 0x2822(%rip), %rbx      # 0x542e
leaq 0xb0(%rsp), %rsi
movq %rbx, %rdx
callq 0x3826
leaq 0x2622(%rip), %rdi      # 0x5245
leaq 0x40(%rsp), %rsi
movq %rbx, %rdx
callq 0x3826
leaq 0x2618(%rip), %rdi      # 0x524f
leaq 0x30(%rsp), %rsi
movq %rbx, %rdx
callq 0x3826
leaq 0x260d(%rip), %rdi      # 0x5258
leaq 0x50(%rsp), %rsi
movq %rbx, %rdx
callq 0x3826
leaq 0x2609(%rip), %rdi      # 0x5268
leaq 0xa0(%rsp), %r12
movq %r12, %rsi
movq %rbx, %rdx
callq 0x3826
leaq 0x25fa(%rip), %rdi      # 0x5273
leaq 0x10(%rsp), %rsi
movq %rbx, %rdx
callq 0x3826
leaq 0x25f2(%rip), %rdi      # 0x527f
leaq 0x90(%rsp), %r13
movq %r13, %rsi
movq %rbx, %rdx
callq 0x3826
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
leaq 0x25c1(%rip), %rsi      # 0x528f
movl $0x1c, %edx
movq %r15, %rdi
callq 0x2170
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
leaq 0x80(%rsp), %rbx
leaq 0x230(%rsp), %r14
movq %rbx, %rdi
movq %r13, %rsi
movq %r14, %rdx
callq 0x38fc
vmovapd (%rbx), %xmm0
vmovapd %xmm0, 0x70(%rsp)
cmpb $0x1, 0x10(%r14)
jne 0x2d96
leaq 0x254a(%rip), %rsi      # 0x52ac
movl $0x30, %edx
movq %r15, %rdi
callq 0x2170
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
movl $0x8, %edi
callq 0x2160
movq %rax, 0x28(%rsp)
movq $0x0, (%rax)
movl $0x8, %edi
callq 0x2160
movq %rax, %r14
movq $0x0, (%rax)
movb $0x0, 0x436b(%rip)      # 0x7132
movzbl 0x1241(%rsp), %eax
xorl %ebx, %ebx
testl %eax, %eax
je 0x2de2
movl %eax, %ecx
shrl %ecx
incl %ebx
cmpl $0x2, %eax
movl %ecx, %eax
jae 0x2dd7
movb 0x241(%rsp), %al
movzbl 0x230(%rsp), %ecx
movb %al, 0x10(%rsp,%rcx)
movl $0x10c8, %edi           # imm = 0x10C8
callq 0x2160
movq %rax, %rbp
leaq 0x70(%rsp), %rsi
leaq 0x10(%rsp), %rdx
leaq 0x40(%rsp), %rcx
leaq 0x30(%rsp), %r8
leaq 0x50(%rsp), %r9
movq %rax, %rdi
pushq %r13
pushq %r12
callq 0x398a
addq $0x10, %rsp
movq %rbp, (%r14)
leaq 0x24a8(%rip), %rdi      # 0x52dd
xorl %esi, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x2040
leaq 0x24ab(%rip), %rdi      # 0x52f2
leaq 0x25df(%rip), %rdx      # 0x542d
leaq 0x70(%rsp), %rsi
callq 0x3826
movq (%r15), %rax
addq -0x18(%rax), %r15
movq %r15, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq 0x415a(%rip), %rbp      # 0x6fd0
movq %rbp, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
movq %rax, %r15
leaq 0x246b(%rip), %rsi      # 0x52fb
movl $0xb, %edx
movq %rax, %rdi
callq 0x2170
movzbl 0x240(%rsp), %eax
imull %eax, %ebx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x20d0
movq %rax, %rbx
leaq 0x244a(%rip), %rsi      # 0x5307
movl $0xc, %edx
movq %rax, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
callq 0x2190
movq %rax, %r13
movl $0x8, %edi
callq 0x2160
movq %rax, %r15
leaq 0xb79(%rip), %rax       # 0x3a86
leaq 0xf0(%rsp), %rsi
movq %rax, (%rsi)
movq $0x0, 0x8(%rsi)
movq %r15, %rdi
movq %r14, %rdx
callq 0x3ba6
movq 0x28(%rsp), %rax
movq %r15, (%rax)
movq %r15, %rdi
callq 0x21f0
movq (%r14), %rax
movb 0x8(%rax), %cl
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movb %cl, 0xf(%rsp)
cmpb $0x1, %cl
jne 0x2f5f
vmovupd 0x1030(%rax), %xmm0
vmovapd %xmm0, 0x10(%rsp)
xorl %ebx, %ebx
movq (%rax), %r15
callq 0x2190
movq %rax, %r12
movq (%rbp), %rax
addq -0x18(%rax), %rbp
movq %rbp, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq 0x4047(%rip), %rbp      # 0x6fd0
movq %rbp, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
cmpb $0x0, 0xf(%rsp)
je 0x301e
movq 0x4029(%rip), %rdi      # 0x6fd0
leaq 0x2366(%rip), %rsi      # 0x5314
movl $0xb, %edx
callq 0x2170
movq 0x4011(%rip), %rdi      # 0x6fd0
movl %ebx, %esi
callq 0x2200
movq %rax, %rbx
leaq 0x2350(%rip), %rsi      # 0x5320
movl $0x28, %edx
movq %rax, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
leaq 0x233e(%rip), %rdi      # 0x5349
leaq 0x241c(%rip), %rdx      # 0x542e
leaq 0x10(%rsp), %rsi
callq 0x3826
jmp 0x3064
movq 0x3fab(%rip), %rbx      # 0x6fd0
leaq 0x2330(%rip), %rsi      # 0x535c
movl $0x23, %edx
movq %rbx, %rdi
callq 0x2170
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq 0x3f79(%rip), %rdi      # 0x6fd0
callq 0x2030
movq %rax, %rdi
callq 0x20e0
movq (%rbp), %rax
addq -0x18(%rax), %rbp
movq %rbp, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq 0x3f4d(%rip), %rdi      # 0x6fd0
callq 0x2030
movq %rax, %rdi
callq 0x20e0
movq %rax, %rbx
leaq 0x22e6(%rip), %rsi      # 0x5380
movl $0x11, %edx
movq %rax, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
movq 0x3efb(%rip), %rbx      # 0x6fd0
leaq 0x217a(%rip), %rsi      # 0x5256
movl $0x1, %edx
movq %rbx, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rax
movl 0x18(%rbx,%rax), %ecx
andl $-0x4b, %ecx
orl $0x2, %ecx
movl %ecx, 0x18(%rbx,%rax)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x20d0
leaq 0x2282(%rip), %rsi      # 0x5392
movl $0x1b, %edx
movq %rax, %rdi
callq 0x2170
subq %r13, %r12
vcvtsi2sd %r12, %xmm0, %xmm0
vmulsd 0x1f23(%rip), %xmm0, %xmm0 # 0x5050
movq 0x3e9c(%rip), %rdi      # 0x6fd0
vmovsd %xmm0, 0x68(%rsp)
callq 0x21c0
movq %rax, %rbx
leaq 0x2308(%rip), %rsi      # 0x5451
movl $0x1, %edx
movq %rax, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
testq %r15, %r15
je 0x3295
movq 0x3e43(%rip), %rdi      # 0x6fd0
leaq 0x20c2(%rip), %rsi      # 0x5256
movl $0x1, %edx
callq 0x2170
movq %r12, %rax
xorl %edx, %edx
divq %r15
movl %eax, %esi
movq 0x3e21(%rip), %rdi      # 0x6fd0
callq 0x20d0
movq %rax, %rbx
leaq 0x21f0(%rip), %rsi      # 0x53ae
movl $0x18, %edx
movq %rax, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
vcvtusi2sd %r15, %xmm1, %xmm0
vdivsd 0x68(%rsp), %xmm0, %xmm0
vcvttsd2usi %xmm0, %rbx
cmpq $0xf4241, %rbx          # imm = 0xF4241
jb 0x329f
movq 0x3db8(%rip), %r15      # 0x6fd0
leaq 0x2037(%rip), %rsi      # 0x5256
movl $0x1, %edx
movq %r15, %rdi
callq 0x2170
movq (%r15), %rax
movq -0x18(%rax), %rcx
movl $0xfffffefb, %edx       # imm = 0xFFFFFEFB
andl 0x18(%r15,%rcx), %edx
orl $0x4, %edx
movl %edx, 0x18(%r15,%rcx)
movq -0x18(%rax), %rax
movq $0x2, 0x8(%r15,%rax)
vcvtusi2sd %rbx, %xmm1, %xmm0
vmulsd 0x1df8(%rip), %xmm0, %xmm0 # 0x5058
movq %r15, %rdi
callq 0x21c0
movq %rax, %rbx
leaq 0x2155(%rip), %rsi      # 0x53c7
movl $0x1b, %edx
movq %rax, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
jmp 0x32f1
movl $0x1, %ebp
jmp 0x343d
movq 0x3d2a(%rip), %rdi      # 0x6fd0
leaq 0x1fa9(%rip), %rsi      # 0x5256
movl $0x1, %edx
callq 0x2170
movq 0x3d12(%rip), %rdi      # 0x6fd0
movq %rbx, %rsi
callq 0x20d0
movq %rax, %rbx
leaq 0x2113(%rip), %rsi      # 0x53e3
movl $0x12, %edx
movq %rax, %rdi
callq 0x2170
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
xorl %ebp, %ebp
cmpb $0x0, 0xf(%rsp)
je 0x343d
vxorpd %xmm0, %xmm0, %xmm0
leaq 0xe0(%rsp), %r15
vmovapd %xmm0, (%r15)
leaq 0xc0(%rsp), %rbx
vmovapd %xmm0, (%rbx)
movb $0x0, 0x10(%rbx)
vxorpd %xmm0, %xmm0, %xmm0
leaq 0xf0(%rsp), %r12
vmovupd %zmm0, 0x100(%r12)
vmovupd %zmm0, 0xc0(%r12)
vmovupd %zmm0, 0x80(%r12)
vmovupd %zmm0, 0x40(%r12)
vmovupd %zmm0, (%r12)
leaq 0x40(%rsp), %rdi
movq %r12, %rsi
vzeroupper
callq 0x35c5
vmovdqa 0xa0(%r12), %xmm0
leaq 0x10(%rsp), %rsi
vpxor (%rsi), %xmm0, %xmm0
vaesdec 0xb0(%r12), %xmm0, %xmm0
vaesdec 0xc0(%r12), %xmm0, %xmm0
vaesdec 0xd0(%r12), %xmm0, %xmm0
vaesdec 0xe0(%r12), %xmm0, %xmm0
vaesdec 0xf0(%r12), %xmm0, %xmm0
vaesdec 0x100(%r12), %xmm0, %xmm0
vaesdec 0x110(%r12), %xmm0, %xmm0
vaesdec 0x120(%r12), %xmm0, %xmm0
vaesdec 0x130(%r12), %xmm0, %xmm0
vaesdeclast (%r12), %xmm0, %xmm0
vpxor 0x30(%rsp), %xmm0, %xmm0
vmovdqa %xmm0, (%r15)
vmovdqa %xmm0, (%rbx)
leaq 0x1ff8(%rip), %rdi      # 0x53f6
leaq 0x2029(%rip), %r12      # 0x542e
movq %r12, %rdx
callq 0x3826
leaq 0x1ff3(%rip), %rdi      # 0x5407
movq %r15, %rsi
movq %r12, %rdx
callq 0x3826
movq %rbx, %rdi
callq 0x2070
leaq 0x1fe9(%rip), %rdi      # 0x5417
xorl %ebp, %ebp
movq %rbx, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x2040
movq %r14, %rdi
callq 0x2130
movq 0x28(%rsp), %rdi
callq 0x2130
movl %ebp, %eax
addq $0x3268, %rsp           # imm = 0x3268
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x3b86(%rip), %rdi      # 0x6ff0
leaq 0x1d12(%rip), %rsi      # 0x5183
callq 0x2150
movq %rax, %rdi
callq 0x2090
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2180
leaq 0x1d13(%rip), %rdi      # 0x51a2
leaq 0x1d16(%rip), %rsi      # 0x51ac
leaq 0x1d27(%rip), %rcx      # 0x51c4
movl $0x1b0, %edx            # imm = 0x1B0
callq 0x20c0
leaq 0x1cf4(%rip), %rdi      # 0x51a2
leaq 0x1cf7(%rip), %rsi      # 0x51ac
leaq 0x1d08(%rip), %rcx      # 0x51c4
movl $0x1b2, %edx            # imm = 0x1B2
callq 0x20c0
leaq 0x1cd5(%rip), %rdi      # 0x51a2
leaq 0x1cd8(%rip), %rsi      # 0x51ac
leaq 0x1ce9(%rip), %rcx      # 0x51c4
movl $0x1b4, %edx            # imm = 0x1B4
callq 0x20c0
leaq 0x1cb6(%rip), %rdi      # 0x51a2
leaq 0x1cb9(%rip), %rsi      # 0x51ac
leaq 0x1cca(%rip), %rcx      # 0x51c4
movl $0x1b6, %edx            # imm = 0x1B6
callq 0x20c0
leaq 0x1c97(%rip), %rdi      # 0x51a2
leaq 0x1c9a(%rip), %rsi      # 0x51ac
leaq 0x1cab(%rip), %rcx      # 0x51c4
movl $0x1b8, %edx            # imm = 0x1B8
callq 0x20c0
leaq 0x1c78(%rip), %rdi      # 0x51a2
leaq 0x1c7b(%rip), %rsi      # 0x51ac
leaq 0x1c8c(%rip), %rcx      # 0x51c4
movl $0x1ba, %edx            # imm = 0x1BA
callq 0x20c0
leaq 0x1c59(%rip), %rdi      # 0x51a2
leaq 0x1c5c(%rip), %rsi      # 0x51ac
leaq 0x1c6d(%rip), %rcx      # 0x51c4
movl $0x1bc, %edx            # imm = 0x1BC
callq 0x20c0
leaq 0x1c3a(%rip), %rdi      # 0x51a2
leaq 0x1c3d(%rip), %rsi      # 0x51ac
leaq 0x1c4e(%rip), %rcx      # 0x51c4
movl $0x1be, %edx            # imm = 0x1BE
callq 0x20c0
jmp 0x35a8
movq %rax, %rbx
movq %r15, %rdi
jmp 0x3592
jmp 0x35a8
movq %rax, %rbx
movq %rbp, %rdi
callq 0x2130
jmp 0x35ab
jmp 0x35a8
movq %rax, %rbx
jmp 0x35b3
jmp 0x35a8
jmp 0x35a8
jmp 0x35a8
jmp 0x35a8
movq %rax, %rbx
movq %r14, %rdi
callq 0x2130
movq 0x28(%rsp), %rdi
callq 0x2130
movq %rbx, %rdi
callq 0x2210