---
# System prepended metadata

title: Dreamhack Reverse Engineering
tags: [dreamhack]

---

---
title: 'Dreamhack Reverse Engineering'
tags: [dreamhack]
---

# Casino777
> Link: https://dreamhack.io/wargame/challenges/143

#### Description:
Regrettably, Dream didn't go to Las Vegas during Defcon last year, so he made his own slot machine. Hit the jackpot and win the flag!

#### General: 
Our always first step is decompiling it using IDA.

```C
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  int n2; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v5; // [rsp+8h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  introduce();
  while ( 1 )
  {
    printf("> ");
    n2 = 0;
    if ( (int)__isoc99_scanf("%d", &n2) <= 0 )
      break;
    if ( n2 == 1 )
    {
      generate_slot();
    }
    else if ( n2 == 2 )
    {
      rotate_slot();
    }
    else
    {
      puts("Nope");
    }
  }
  return 0LL;
}
```
It is clearly that this is a kernel of the program, which processes and handles our next steps!

Lets check generate_slot() and rotate_slot(). 

```C
int generate_slot()
{
  __int64 v0; // rbx
  __int64 v1; // rbx
  char n55; // [rsp+Fh] [rbp-21h]
  int counter; // [rsp+10h] [rbp-20h]
  int v5; // [rsp+14h] [rbp-1Ch]
  int j; // [rsp+18h] [rbp-18h]
  int size; // [rsp+1Ch] [rbp-14h]

  for ( counter = 0; counter <= 9; ++counter )
  {
    *((_QWORD *)&addr + counter) = malloc(16uLL);
    size = *(_DWORD *)&asc_4080[4 * counter] + 1;// "H"
    **((_DWORD **)&addr + counter) = size;
    v0 = *((_QWORD *)&addr + counter);
    *(_QWORD *)(v0 + 8) = malloc(size);
    v5 = 0;
    for ( j = 0; j < size; ++j )
    {
      n55 = aAbcdefghijklmn[(unsigned __int8)random_from_devurandom() % 94u];// "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
      *(_BYTE *)(j + *(_QWORD *)(*((_QWORD *)&addr + counter) + 8LL)) = n55;
      if ( n55 == 55 )
        v5 = 1;
    }
    if ( !v5 )
    {
      v1 = *(_QWORD *)(*((_QWORD *)&addr + counter) + 8LL);
      *(_BYTE *)(v1 + (unsigned __int8)random_from_devurandom() % size) = 55;
    }
  }
  counter_something = 1;
  return puts("slot generated !");
}
```

```C
unsigned __int64 rotate_slot()
{
  int counter; // [rsp+Ch] [rbp-134h]
  int i; // [rsp+10h] [rbp-130h]
  int v3; // [rsp+14h] [rbp-12Ch]
  int j; // [rsp+18h] [rbp-128h]
  int fd; // [rsp+1Ch] [rbp-124h]
  int size; // [rsp+20h] [rbp-120h]
  int v7; // [rsp+24h] [rbp-11Ch]
  unsigned __int64 v8; // [rsp+28h] [rbp-118h] BYREF
  char src[264]; // [rsp+30h] [rbp-110h] BYREF
  unsigned __int64 COOKIE; // [rsp+138h] [rbp-8h]

  COOKIE = __readfsqword(0x28u);
  v8 = 0LL;
  if ( counter_something )
  {
    ++counter_something;
    puts("How many rotate the slots ?");
    printf("> ");
    __isoc99_scanf("%lld", &v8);
    for ( counter = 0; counter <= 9; ++counter )
    {
      size = **((_DWORD **)&addr + counter);
      v7 = v8 % size;
      memset(src, 0, 256);
      for ( i = 0; i < size; ++i )
        src[(i + v7) % size] = *(_BYTE *)(*(_QWORD *)(*((_QWORD *)&addr + counter) + 8LL) + i);
      memcpy(*(void **)(*((_QWORD *)&addr + counter) + 8LL), src, size);
    }
    v3 = 1;
    printf("Result: ");
    for ( j = 0; j <= 9; ++j )
    {
      printf("%c ", (unsigned int)**(char **)(*((_QWORD *)&addr + j) + 8LL));
      if ( **(_BYTE **)(*((_QWORD *)&addr + j) + 8LL) != 55 )
        v3 = 0;
    }
    putchar(10);
    if ( v3 )
    {
      puts("Jackpot ! Congratuations !!");
      fd = open("flag", 0);
      memset(src, 0, 256);
      read(fd, src, 0x100uLL);
      puts(src);
    }
  }
  else
  {
    puts("Generate the slots first !");
  }
  return __readfsqword(0x28u) ^ COOKIE;
}
```
> [!Note]
> I have renamed some struct in order to retrieve a better vision for this solution

Well, the logic is basically, there is 9 slots in the slot machine, each of slot is first initliazed randomly when using the first operation! After that the input we type when using 2nd operation (temporarily call it x) is for rolling ALL slots x times. In order to get the flag, we need to hit jackpot which require all slots to be stopped at 7

So our solution is clear, we can retrieve the position of 7 in all slots by using some several second type operation. After that we just need only 1 number of x that rotate all the slots that match the Jackpot condition. And thats magic X number can be found by using CRT (Chinese remainder theorem)

> [!Note]
> CRT might produces an overflowed solution (which exceed the unsigned 64 bit integer limit). So you should try serveral times to get correct answer

#### Script:
```python
#!/home/ryou/.venvs/re/bin/python

import math
from pwn import *

context.binary = exe = ELF('./casino_777', checksec=False)

# p = process(exe.path)
p = remote('host8.dreamhack.games', 14261)

# sleep(1)
while True:
    p.sendlineafter(b'>', b'1')
    size = [73, 83, 89, 97, 103, 79, 101, 127, 131, 137]
    addr = []
    for i in size:
        addr.append([0] * i)

    def rot(turn: int):
        for i in range(10):
            k = turn % len(addr[i])
            addr[i] = addr[i][-k:] + addr[i][:-k]
        return

    def sendPayload(turn: int) -> list:
        p.sendlineafter(b'>', b'2')
        p.sendlineafter(b'slots ?', str(turn).encode())
        p.recvuntil(b'Result: ')
        return [ord(i) for i in p.recvline().decode().split(' ') if ord(i) != 10]

    cur = sendPayload(0)
    for _ in range(140):
        for i in range(10):
            if cur[i] == 0x37:
                addr[i][0] = 1
        cur = sendPayload(1)
        rot(1)
        

    def crt(congruences):
        if not congruences:
            return 0, 1  

        mod, rem = congruences[0]
        x, m = rem % mod, mod

        for mod, rem in congruences[1:]:
            rem %= mod

            g = math.gcd(m, mod)
            diff = rem - x
            if diff % g != 0:
                return None, None  

            m1 = m // g
            m2 = mod // g
            diff //= g

            inv_m1 = pow(m1, -1, m2)
            k = (diff * inv_m1) % m2

            x = x + m * k
            m = m * m2       
            x %= m           

        return x, m

    congruences = []
    for i in range(10):
        congruences.append((size[i], 
            size[i] - addr[i].index(1)           
            ))

    res = crt(congruences)
    if len(str(res[0])) >= 20:
        continue
    G = sendPayload(res[0])
    print(G)
    break

p.interactive()

```

# Rivest
> Link: https://dreamhack.io/wargame/challenges/2278

#### Description:
Reverse a legacy algorithm still seen in malware.

#### General:
Our first step always finds the download button and download it!

At first glance, when we are trying to decompile it using IDA PRO it seems to be packed by UPX. So in order to solve the problem we should first, unpacking it and then dancing in those punch of lines of code.

```bash
sudo apt install upx
upx -d ./chall
```

This is what punchs into our eyes when open 
```assembly
; Attributes: noreturn fuzzy-sp

public start
start proc near
; __unwind {
endbr64
xor     ebp, ebp
mov     r9, rdx         ; rtld_fini
pop     rsi             ; argc
mov     rdx, rsp        ; ubp_av
and     rsp, 0FFFFFFFFFFFFFFF0h
push    rax
push    rsp             ; stack_end
xor     r8d, r8d        ; fini
xor     ecx, ecx        ; init
lea     rdi, main       ; main
call    cs:__libc_start_main_ptr
hlt
; } // starts at 1490
start endp
```

Without any hesitate, explore the main function

```C
__int64 __fastcall main(int n2, char **args, char **input)
{
  _BYTE *v5; // r9
  int n7; // r8d
  int n11; // edi
  __int64 i; // rdx
  __int64 v9; // rax
  char v10; // si
  unsigned int i_1; // kr00_4
  _DWORD *s1_1; // rdi
  __int64 n20; // rcx
  _DWORD *v14; // rsi
  __int64 n20_1; // rcx
  _DWORD *v16; // rdi
  _DWORD *s1_2; // rsi
  __int64 v18; // r14
  __int64 v19; // rax
  _BYTE *v20; // rdi
  _BYTE *v21; // r9
  int n7_1; // r8d
  __int64 j; // rdx
  char v24; // si
  unsigned int j_1; // kr04_4
  __int64 n9; // rcx
  _DWORD *s1_3; // rdi
  _DWORD *v28; // rsi
  const char *OK; // rdi
  int v30; // [rsp+Ch] [rbp-16Ch]
  int n16; // [rsp+14h] [rbp-164h] BYREF
  __int64 v32; // [rsp+18h] [rbp-160h] BYREF
  _BYTE v33[16]; // [rsp+20h] [rbp-158h] BYREF
  _BYTE v34[16]; // [rsp+30h] [rbp-148h] BYREF
  _BYTE s1[80]; // [rsp+40h] [rbp-138h] BYREF
  _BYTE v36[168]; // [rsp+90h] [rbp-E8h] BYREF
  unsigned __int64 st_canary; // [rsp+138h] [rbp-40h]

  st_canary = __readfsqword(0x28u);
  if ( n2 != 2 )
  {
    fprintf(stderr, "usage: %s <flag>\n", *args);
    return 1LL;
  }
  v5 = v34;
  n7 = 7;
  n11 = 11;
  for ( i = 0LL; i != 16; ++i )
  {
    ++v5;
    v9 = n11 & 0xF;
    n11 += 5;
    v10 = byte_2060[v9] ^ n7 ^ byte_20D0[i];
    n7 += 13;
    i_1 = i;
    *(v5 - 1) = __ROL1__(v10, i_1 % 7);
  }
  s1_1 = s1;
  n20 = 20LL;
  v14 = &unk_2080;
  while ( n20 )
  {
    *s1_1++ = *v14++;
    --n20;
  }
  sub_15E0((__int64)v34, s1, 0x50);
  n20_1 = 20LL;
  v16 = v36;
  s1_2 = s1;
  v36[80] = 0;
  while ( n20_1 )
  {
    *v16++ = *s1_2++;
    --n20_1;
  }
  if ( (unsigned int)curl_global_init(3LL, (__int64)s1_2) )
    return 2LL;
  v18 = curl_easy_init();
  if ( !v18 )
  {
    curl_global_cleanup();
    return 2LL;
  }
  v32 = EVP_MD_CTX_new();
  if ( !v32 )
  {
    curl_easy_cleanup(v18);
    curl_global_cleanup();
    return 2LL;
  }
  v19 = EVP_md5();
  EVP_DigestInit_ex(v32, v19, 0LL);
  curl_easy_setopt(v18, 10002LL, (__int64)v36);
  curl_easy_setopt(v18, 52LL, 1LL);
  curl_easy_setopt(v18, 10018LL, (__int64)"M");
  curl_easy_setopt(v18, 20011LL, (__int64)sub_15C0);
  curl_easy_setopt(v18, 10001LL, (__int64)&v32);
  v30 = curl_easy_perform(v18);
  curl_easy_cleanup(v18);
  curl_global_cleanup();
  if ( v30 )
  {
    EVP_MD_CTX_free(v32);
    puts("NO");
    return 3LL;
  }
  n16 = 0;
  EVP_DigestFinal_ex(v32, (__int64)v33, (__int64)&n16);
  EVP_MD_CTX_free(v32);
  if ( n16 != 16 )
  {
    puts("NO");
    return 3LL;
  }
  v20 = v33;
  v21 = v34;
  n7_1 = 7;
  for ( j = 0LL; j != 16; ++j )
  {
    ++v20;
    ++v21;
    v24 = v33[((_BYTE)j + 7) & 0xF] ^ *(v20 - 1) ^ n7_1 ^ byte_20D0[j];
    n7_1 += 31;
    j_1 = j;
    *(v21 - 1) = __ROL1__(v24, j_1 % 7);
  }
  n9 = 9LL;
  s1_3 = s1;
  v28 = &unk_2020;
  while ( n9 )
  {
    *s1_3++ = *v28++;
    --n9;
  }
  sub_15E0((__int64)v34, s1, 36);
  if ( !memcmp(s1, args[1], 0x24uLL) )
    OK = "OK";
  else
    OK = "NO";
  puts(OK);
  return 0LL;
}
```

The C pseudocode is kinda... a mess. But just lets unpacking it slowly

Generally, we can figure out that the main idea of this code is first getting our argument from command `./chall <flag>` then from `byte_2060` `byte_20D0` `unk_2020` and `unk_2080` with the function `sub_15E0` and thousand of combination of mathematical operations, all together just to generate a flag by some logic thats we will be trying to find out now

Now first of all we need to figure out what the function `sub_15E0` due to the fact that it likely the main encrypting/decrypting part

```C
unsigned __int64 __fastcall sub_15E0(__int64 a1, _BYTE *s1, int n80)
{
  __m128i v5; // xmm5
  __m128i si128; // xmm2
  __m128i *v8; // rax
  __m128i v9; // xmm9
  __m128i v10; // xmm8
  __m128i v11; // xmm7
  __m128i v12; // xmm6
  __m128i v13; // xmm3
  __m128i v14; // xmm0
  __m128i v15; // xmm4
  __m128i v16; // xmm3
  __m128i v17; // xmm1
  __m128i v18; // xmm3
  __m128i si128_1; // xmm0
  __m128i v20; // xmm1
  __m128i v21; // xmm3
  __m128i v22; // xmm0
  __m128i v23; // xmm3
  char *SBOX; // rdx
  int v25; // ecx
  int n256; // eax
  char n256_1; // si
  int v28; // edi
  char *v29; // rcx
  _BYTE *s1_1; // rdx
  int v31; // esi
  int v32; // eax
  char v34; // [rsp+0h] [rbp-118h] BYREF
  char v35; // [rsp+1h] [rbp-117h] BYREF
  char v36; // [rsp+100h] [rbp-18h] BYREF
  unsigned __int64 st_canary; // [rsp+108h] [rbp-10h]

  v5 = _mm_srli_epi16((__m128i)-1LL, 8u);
  st_canary = __readfsqword(0x28u);
  si128 = _mm_load_si128((const __m128i *)&xmmword_20E0);
  v8 = (__m128i *)&v34;
  v9 = _mm_shuffle_epi32(_mm_cvtsi32_si128(4u), 0);
  v10 = _mm_shuffle_epi32(_mm_cvtsi32_si128(8u), 0);
  v11 = _mm_shuffle_epi32(_mm_cvtsi32_si128(0xCu), 0);
  v12 = _mm_shuffle_epi32(_mm_cvtsi32_si128(0x10u), 0);
  do
  {
    ++v8;
    v13 = _mm_add_epi32(si128, v9);
    v14 = _mm_unpackhi_epi16(si128, v13);
    v15 = _mm_add_epi32(si128, v11);
    v16 = _mm_unpacklo_epi16(si128, v13);
    v17 = _mm_unpacklo_epi16(v16, v14);
    v18 = _mm_unpackhi_epi16(v16, v14);
    si128_1 = si128;
    si128 = _mm_add_epi32(si128, v12);
    v20 = _mm_unpacklo_epi16(v17, v18);
    v21 = _mm_add_epi32(si128_1, v10);
    v22 = _mm_unpacklo_epi16(v21, v15);
    v23 = _mm_unpackhi_epi16(v21, v15);
    v8[-1] = _mm_packus_epi16(
               _mm_and_si128(v20, v5),
               _mm_and_si128(_mm_unpacklo_epi16(_mm_unpacklo_epi16(v22, v23), _mm_unpackhi_epi16(v22, v23)), v5));
  }
  while ( v8 != (__m128i *)&v36 );
  SBOX = &v34;
  v25 = 0;
  n256 = 0;
  do
  {
    n256_1 = n256;
    v28 = (unsigned __int8)*SBOX;
    ++n256;
    ++SBOX;
    v25 += v28 + *(unsigned __int8 *)(a1 + (n256_1 & 0xF));
    *(SBOX - 1) = *(&v34 + (unsigned __int8)v25);
    *(&v34 + (unsigned __int8)v25) = v28;
  }
  while ( n256 != 256 );
  v29 = &v35;
  s1_1 = s1;
  v31 = 0;
  do
  {
    v32 = (unsigned __int8)*v29++;
    v31 += v32;
    *(v29 - 1) = *(&v34 + (unsigned __int8)v31);
    *(&v34 + (unsigned __int8)v31) = v32;
    *s1_1++ ^= *(&v34 + (unsigned __int8)(*(v29 - 1) + v32));
  }
  while ( s1_1 != &s1[n80] );
  return st_canary - __readfsqword(0x28u);
}
```

This function is similar to RC4 algorithm so we can transfer it to python version like this

```python
def  sub_15E0(key: bytes, s: bytearray, n: int):
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i & 0x0F]) & 0xFF 
        S[i], S[j] = S[j], S[i]

    j = 0
    for i in range(n):               
        idx = (i + 1) & 0xFF                   
        a = S[idx]
        j = (j + a) & 0xFF
        S[idx], S[j] = S[j], a
        s[i] ^= S[(S[idx] + S[j]) & 0xFF]
```


Next we can see that there are punch of weird functions like `curl_....()` or `EVP_...` sound like belong to HTTPS Request things

So the first half of the program is generating the url by some const `byte_2060` and `byte_20D0` and `unk_2080`

So we can easily move this logic to python but first of all we have to filter data from .rodata (those aforementioned value)

```python 
unk2080_data = """
.rodata:0000000000002080                 db  2Fh ; /          
.rodata:0000000000002081                 db  57h ; W
<.....................more here....................>
<.....................more here....................>
<.....................more here....................>
.rodata:00000000000020CD                 db  77h ; w
.rodata:00000000000020CE                 db 0AFh
.rodata:00000000000020CF                 db 0CBh
"""
unk2020_data = """
.rodata:0000000000002020                 db 0F8h                
.rodata:0000000000002021                 db  40h ; @
.rodata:0000000000002022                 db 0A3h
.rodata:0000000000002023                 db  47h ; G
<.....................more here....................>
<.....................more here....................>
<.....................more here....................>
.rodata:000000000000205C                 db    0
.rodata:000000000000205D                 db    0
.rodata:000000000000205E                 db    0
.rodata:000000000000205F                 db    0
"""

change = lambda x: x if len(x) == 1 else x[:-1]
unk_2080 = [int(change(i), 16) for i in re.split(r"(?:db| |\n|\s|\t|;\s*\S+|\.rodata:\S*)+", unk2080_data) if len(i) != 0]
unk_2020 = [int(change(i), 16) for i in re.split(r"(?:db| |\n|\s|\t|;\s*\S+|\.rodata:\S*)+", unk2020_data) if len(i) != 0]
# print(len(unk_2080))

byte_2060 = [0x55, 0x0A7, 0x19, 0x0C3, 0x2D, 0x0E8, 0x7B, 0x90, 0x34, 0x0DA,
             0x66, 0x11, 0x0B9, 0x4F, 0x80, 0x0CE, 0x0, 0x0, 0x0, 0x0, 0x0, 
             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
byte_20D0 = [0x13, 0x37, 0x0DE, 0x0AD, 0x0BE, 0x0EF, 0x42, 0x99, 0x0, 0x0C0,
             0x0FF, 0x0EE, 0x21, 0x7, 0x0D4, 0x55]

```

Then we have

`__ROL1__ is just a function in order to rotate 8 bit x value y bit left`
```python
__ROL1__ = lambda x, y: (((x & 0xFF) << (y & 7)) | ((x & 0xFF) >> (8 - (y & 7)))) & 0xFF

arr = []
x, y = 7, 11
for i in range(16):
    v9 = y & 0xF
    y += 5
    v10 = byte_2060[v9] ^ x ^ byte_20D0[i]
    x += 13
    arr.append(__ROL1__(v10, i % 7))

s1 = bytearray(unk_2080[:80])

sub_15E0(arr, s1, 80)
```
URL is https://ia804503.us.archive.org/15/items/kikTXNL6MvX6ZpRXM/kikTXNL6MvX6ZpRXM.mp4 
> [!Warning]
> This is a rickroll link :(

Using chatgpt to create a https request we can find that we get the value

`e6b9ef51a73a7e1aee6e95d89ba12208`

Things are more comfortable now just code the python script base on the rest of C pseudocode we have

```python
v33 = [int(value[i:(i+2)], 16) for i in range(0, len(value), 2)]

n7_1 = 7
for i in range(16):
    v24 = v33[ (i + 7) & 0xF ] ^ v33[i] ^ n7_1 ^ byte_20D0[i]
    n7_1 += 31
    arr[i] = __ROL1__(v24, i % 7)

s1 = unk_2020[:9*4]
sub_15E0(arr, s1, 36)
print(bytes(s1).decode())
```

Full code

```python 
import re

# data handle

unk2080_data = """
.rodata:0000000000002080                 db  2Fh ; /          
.rodata:0000000000002081                 db  57h ; W
.rodata:0000000000002082                 db 0A7h
.rodata:0000000000002083                 db 0C5h
.rodata:0000000000002084                 db  7Bh ; {
.rodata:0000000000002085                 db  27h ; '
.rodata:0000000000002086                 db  65h ; e
.rodata:0000000000002087                 db    6
.rodata:0000000000002088                 db 0B2h
.rodata:0000000000002089                 db  2Bh ; +
.rodata:000000000000208A                 db 0A8h
.rodata:000000000000208B                 db 0BAh
.rodata:000000000000208C                 db  4Fh ; O
.rodata:000000000000208D                 db  45h ; E
.rodata:000000000000208E                 db 0DDh
.rodata:000000000000208F                 db  4Bh ; K
.rodata:0000000000002090                 db 0D2h
.rodata:0000000000002091                 db 0DFh
.rodata:0000000000002092                 db  10h
.rodata:0000000000002093                 db  34h ; 4
.rodata:0000000000002094                 db 0C8h
.rodata:0000000000002095                 db  0Fh
.rodata:0000000000002096                 db    9
.rodata:0000000000002097                 db 0A1h
.rodata:0000000000002098                 db  65h ; e
.rodata:0000000000002099                 db  0Ch
.rodata:000000000000209A                 db  2Dh ; -
.rodata:000000000000209B                 db 0D5h
.rodata:000000000000209C                 db 0DEh
.rodata:000000000000209D                 db  69h ; i
.rodata:000000000000209E                 db  45h ; E
.rodata:000000000000209F                 db  0Dh
.rodata:00000000000020A0                 db 0F6h
.rodata:00000000000020A1                 db  15h
.rodata:00000000000020A2                 db  1Fh
.rodata:00000000000020A3                 db 0F9h
.rodata:00000000000020A4                 db  93h
.rodata:00000000000020A5                 db 0ECh
.rodata:00000000000020A6                 db  27h ; '
.rodata:00000000000020A7                 db  2Ch ; ,
.rodata:00000000000020A8                 db  84h
.rodata:00000000000020A9                 db  3Eh ; >
.rodata:00000000000020AA                 db  11h
.rodata:00000000000020AB                 db 0D1h
.rodata:00000000000020AC                 db  46h ; F
.rodata:00000000000020AD                 db 0E2h
.rodata:00000000000020AE                 db    3
.rodata:00000000000020AF                 db 0E7h
.rodata:00000000000020B0                 db  6Dh ; m
.rodata:00000000000020B1                 db  8Eh
.rodata:00000000000020B2                 db 0BDh
.rodata:00000000000020B3                 db 0D6h
.rodata:00000000000020B4                 db  69h ; i
.rodata:00000000000020B5                 db  86h
.rodata:00000000000020B6                 db  0Bh
.rodata:00000000000020B7                 db  5Bh ; [
.rodata:00000000000020B8                 db 0C9h
.rodata:00000000000020B9                 db 0D3h
.rodata:00000000000020BA                 db 0A2h
.rodata:00000000000020BB                 db  22h ; "
.rodata:00000000000020BC                 db  34h ; 4
.rodata:00000000000020BD                 db  3Dh ; =
.rodata:00000000000020BE                 db 0E8h
.rodata:00000000000020BF                 db  7Dh ; }
.rodata:00000000000020C0                 db  11h
.rodata:00000000000020C1                 db  78h ; x
.rodata:00000000000020C2                 db  3Fh ; ?
.rodata:00000000000020C3                 db 0EAh
.rodata:00000000000020C4                 db 0BAh
.rodata:00000000000020C5                 db  42h ; B
.rodata:00000000000020C6                 db 0B9h
.rodata:00000000000020C7                 db  3Eh ; >
.rodata:00000000000020C8                 db  86h
.rodata:00000000000020C9                 db 0F4h
.rodata:00000000000020CA                 db  6Fh ; o
.rodata:00000000000020CB                 db  1Ch
.rodata:00000000000020CC                 db  25h ; %
.rodata:00000000000020CD                 db  77h ; w
.rodata:00000000000020CE                 db 0AFh
.rodata:00000000000020CF                 db 0CBh
"""
unk2020_data = """
.rodata:0000000000002020                 db 0F8h                
.rodata:0000000000002021                 db  40h ; @
.rodata:0000000000002022                 db 0A3h
.rodata:0000000000002023                 db  47h ; G
.rodata:0000000000002024                 db 0A1h
.rodata:0000000000002025                 db 0EAh
.rodata:0000000000002026                 db 0AEh
.rodata:0000000000002027                 db  50h ; P
.rodata:0000000000002028                 db 0F9h
.rodata:0000000000002029                 db 0A5h
.rodata:000000000000202A                 db  52h ; R
.rodata:000000000000202B                 db  55h ; U
.rodata:000000000000202C                 db  42h ; B
.rodata:000000000000202D                 db 0D0h
.rodata:000000000000202E                 db  2Dh ; -
.rodata:000000000000202F                 db  16h
.rodata:0000000000002030                 db  78h ; x
.rodata:0000000000002031                 db  53h ; S
.rodata:0000000000002032                 db 0CDh
.rodata:0000000000002033                 db  3Ch ; <
.rodata:0000000000002034                 db 0E8h
.rodata:0000000000002035                 db  1Ch
.rodata:0000000000002036                 db  90h
.rodata:0000000000002037                 db 0FEh
.rodata:0000000000002038                 db 0EFh
.rodata:0000000000002039                 db 0A8h
.rodata:000000000000203A                 db  6Eh ; n
.rodata:000000000000203B                 db    3
.rodata:000000000000203C                 db  7Ah ; z
.rodata:000000000000203D                 db  82h
.rodata:000000000000203E                 db  1Ch
.rodata:000000000000203F                 db  0Ch
.rodata:0000000000002040                 db 0A8h
.rodata:0000000000002041                 db  46h ; F
.rodata:0000000000002042                 db  43h ; C
.rodata:0000000000002043                 db 0C5h
.rodata:0000000000002044                 db    0
.rodata:0000000000002045                 db    0
.rodata:0000000000002046                 db    0
.rodata:0000000000002047                 db    0
.rodata:0000000000002048                 db    0
.rodata:0000000000002049                 db    0
.rodata:000000000000204A                 db    0
.rodata:000000000000204B                 db    0
.rodata:000000000000204C                 db    0
.rodata:000000000000204D                 db    0
.rodata:000000000000204E                 db    0
.rodata:000000000000204F                 db    0
.rodata:0000000000002050                 db    0
.rodata:0000000000002051                 db    0
.rodata:0000000000002052                 db    0
.rodata:0000000000002053                 db    0
.rodata:0000000000002054                 db    0
.rodata:0000000000002055                 db    0
.rodata:0000000000002056                 db    0
.rodata:0000000000002057                 db    0
.rodata:0000000000002058                 db    0
.rodata:0000000000002059                 db    0
.rodata:000000000000205A                 db    0
.rodata:000000000000205B                 db    0
.rodata:000000000000205C                 db    0
.rodata:000000000000205D                 db    0
.rodata:000000000000205E                 db    0
.rodata:000000000000205F                 db    0
"""

change = lambda x: x if len(x) == 1 else x[:-1]
unk_2080 = [int(change(i), 16) for i in re.split(r"(?:db| |\n|\s|\t|;\s*\S+|\.rodata:\S*)+", unk2080_data) if len(i) != 0]
unk_2020 = [int(change(i), 16) for i in re.split(r"(?:db| |\n|\s|\t|;\s*\S+|\.rodata:\S*)+", unk2020_data) if len(i) != 0]
# print(len(unk_2080))

byte_2060 = [0x55, 0x0A7, 0x19, 0x0C3, 0x2D, 0x0E8, 0x7B, 0x90, 0x34, 0x0DA,
             0x66, 0x11, 0x0B9, 0x4F, 0x80, 0x0CE, 0x0, 0x0, 0x0, 0x0, 0x0, 
             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
byte_20D0 = [0x13, 0x37, 0x0DE, 0x0AD, 0x0BE, 0x0EF, 0x42, 0x99, 0x0, 0x0C0,
             0x0FF, 0x0EE, 0x21, 0x7, 0x0D4, 0x55]

# creating SBOX 

def  sub_15E0(key: bytes, s: bytearray, n: int):
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i & 0x0F]) & 0xFF 
        S[i], S[j] = S[j], S[i]

    j = 0
    for i in range(n):               
        idx = (i + 1) & 0xFF                   
        a = S[idx]
        j = (j + a) & 0xFF
        S[idx], S[j] = S[j], a
        s[i] ^= S[(S[idx] + S[j]) & 0xFF]


__ROL1__ = lambda x, y: (((x & 0xFF) << (y & 7)) | ((x & 0xFF) >> (8 - (y & 7)))) & 0xFF

arr = []
x, y = 7, 11
for i in range(16):
    v9 = y & 0xF
    y += 5
    v10 = byte_2060[v9] ^ x ^ byte_20D0[i]
    x += 13
    arr.append(__ROL1__(v10, i % 7))

s1 = bytearray(unk_2080[:80])

sub_15E0(arr, s1, 80)

# HTTPS REQUEST
#############################################
import hashlib
import requests
import sys
import time

URL = bytes(s1).decode()

def http_md5_with_progress(url: str, timeout: float = 30.0, chunk_size: int = 256*1024) -> bytes:
    h = hashlib.md5()
    with requests.get(url, stream=True, timeout=timeout, headers={
        "User-Agent": "curl/7.88.1",
        "Accept": "*/*",
    }) as r:
        r.raise_for_status()
        for chunk in r.iter_content(chunk_size):
            if not chunk:
                continue
            h.update(chunk)

    return h.digest()

v33 = http_md5_with_progress(URL)
print(v33.hex())

#############################################

value = "e6b9ef51a73a7e1aee6e95d89ba12208"

v33 = [int(value[i:(i+2)], 16) for i in range(0, len(value), 2)]

n7_1 = 7
for i in range(16):
    v24 = v33[ (i + 7) & 0xF ] ^ v33[i] ^ n7_1 ^ byte_20D0[i]
    n7_1 += 31
    arr[i] = __ROL1__(v24, i % 7)

s1 = unk_2020[:9*4]
sub_15E0(arr, s1, 36)
print(bytes(s1).decode())
```

>[!Important]
>DH{Rc4_N3ver_G0nna_Fad3_Fr0m_M4lwr3}