---
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}