---
# System prepended metadata

title: Разбор тасков с форкбомбы. Часть 1

---

# Разбор тасков с форкбомбы. Часть 1

![](https://i.imgur.com/eTGkdZy.png)

Создано при поддержке [моего канала](https://t.me/lasagnahowto). Все задачи можно найти на rev-kids20.forkbomb.ru

## Lemballovo
Запускаем игру и ловим непонятную ошибку:

![](https://i.imgur.com/LHKb3NF.png)

Закидываем бинарь в иду и по xref-ам находим место, где вылетает ошибка:
![](https://i.imgur.com/mZeviyh.png)

Патчим на

![](https://i.imgur.com/4NmXkdz.png)

И, о чудо, нас ждет уже другая ошибка

![](https://i.imgur.com/AdA9yzZ.png)

Запатчив игру еще пару раз подобным образом, она заработает и выдаст флаг.

![](https://i.imgur.com/cBiiNjm.png)

Полный список адресов, по которым нужно запатчить: 

![](https://i.imgur.com/DR4G79Q.png)


## httpsec
Пропрыгав по xref-ам находим алгоритм получения флага:
```c
int sub_138D()
{
  int v1; // eax
  int v2; // eax
  char v3[136]; // [rsp+0h] [rbp-C0h] BYREF
  FILE *stream; // [rsp+88h] [rbp-38h]
  int v5; // [rsp+94h] [rbp-2Ch]
  char *check_st; // [rsp+98h] [rbp-28h]
  int i; // [rsp+A4h] [rbp-1Ch]
  int res; // [rsp+A8h] [rbp-18h]
  int v9; // [rsp+ACh] [rbp-14h]
  int v10; // [rsp+B0h] [rbp-10h]
  int v11; // [rsp+B4h] [rbp-Ch]
  int v12; // [rsp+B8h] [rbp-8h]
  int v13; // [rsp+BCh] [rbp-4h]

  if ( !strcmp("/", s2) && !strcmp("GET", http_method) )
  {
    puts("HTTP/1.1 200 OK\r\n\r");
    return puts("Welcome to our fast web-server\r");
  }
  else if ( strcmp(s2, "/secret/") == 1 && !strcmp("GET", http_method) )
  {
    check_st = get_header_content("X-Auth");
    if ( check_st )
    {
      st_len = strlen(check_st);
      if ( st_len == 8 )
      {
        v13 = check_st[4] + *check_st - check_st[6];
        v12 = check_st[6] + check_st[3] - check_st[2];
        v11 = check_st[7] + check_st[1] - check_st[3];
        v10 = check_st[2] + check_st[5] - check_st[7];
        v9 = check_st[3] + check_st[1] - check_st[2];
        res = 0;
        for ( i = 0; i <= 7; ++i )
        {
          if ( (v12 & 1) != 0 )
          {
            v10 -= v13;
            if ( (v10 & 1) != 0 )
            {
              v11 -= v9;
              v2 = v12 + v13;
            }
            else
            {
              v12 -= v9;
              v2 = v11 + v12;
            }
            res += v2;
          }
          else
          {
            v9 -= v11;
            if ( (v13 & 1) != 0 )
            {
              v13 -= v12;
              v1 = v10 + v9;
            }
            else
            {
              v10 -= v11;
              v1 = v13 + v12;
            }
            res += v1;
          }
          v13 ^= v12;
          v12 ^= v11;
          v11 ^= v10;
          v10 ^= v9;
          v9 ^= v13;
        }
        if ( res == 444 )
        {
          stream = fopen("flag.txt", "r");
          fgets(v3, 128, stream);
          fclose(stream);
          puts("HTTP/1.1 200 OK\r\n\r");
          return printf("Flag: %s\r\n", v3);
        }
      }
    }
  }
}
```
Попытка решить все это дело с помощью z3 не увенчалась успехом, поэтому пришлось брутить:
```python 
import requests,random


arr = [0]*5
while True:
    st = [random.randint(32,126) for _ in range(8)]
    arr[4] = st[4] + st[0] - st[6]
    arr[3] = st[6] + st[3] - st[2]
    arr[2] = st[7] + st[1] - st[3]
    arr[1] = st[2] + st[5] - st[7]
    arr[0] = st[3] + st[1] - st[2]

    check_var_444 = 0

    for i in range(8):
        if ( (arr[3] & 1) != 0 ):
            arr[1] -= arr[4]
            if ( (arr[1] & 1) != 0 ):
                arr[2] -= arr[0]
                v1 = arr[3] + arr[4]
            else:
                arr[3] -= arr[0]
                v1 = arr[2] + arr[3]
        else:
            arr[0] -= arr[2];
            if ( (arr[4] & 1) != 0 ):
                arr[4] -= arr[3]
                v1 = arr[1] + arr[0]
            else:
                arr[1] -= arr[2];
                v1 = arr[4] + arr[3]
        check_var_444 += v1
        arr[4] ^= arr[3]
        arr[3] ^= arr[2]
        arr[2] ^= arr[1]
        arr[1] ^= arr[0]
        arr[0] ^= arr[4]
    if check_var_444 == 444:
        print(requests.get('http://109.233.56.90:11544/secret/',headers = {"X-Auth": ''.join(map(chr,st))}).content)
        break
```

P.S.: Нужно было сразу брутфорсить, а не загонять в z3, но я подумал, что брутить будет слишком долго. Вот так неверная оценка сложности шифрования может привести к нескольким потерянным часам.

## Gython

~~О нет голанг~~ Закидываем в иду и наслаждаемся псевдокодом.
![](https://i.imgur.com/rtR4kVr.png)

Алгоритм работы бинаря прост -  дропнуть `__init__.pyc` на диск и запустить  ее (в агрументах при этом передается что-то похожее на ключ - `HzURFvGeN7sClEVLJDBnZVnlrTUBDw41RFefNmcB7bdfFg==`).


Вытащить адрес проживания пики можно strace-ом:
![](https://i.imgur.com/aSXQAEw.png)

Декомпилируем пику и получаем следующие:
```python
import base64, hashlib, os, sys, urllib.request
KEY = b'K[\x87\xb7\xddR\x1e\xc0I\x1d/\xa2\xea\xa4\xadGW?Z\xffN\x80k\x9d\xe1\xfc4\xffs\xb2\x86k1'

def byte_xor(ba1, ba2):
    return bytes([_a ^ _b for _a, _b in zip(ba1, ba2)])


def encrypt(key, plaintext):
    while len(key) < len(plaintext):
        key += hashlib.sha256(key).digest()

    key = key[::-1]
    return byte_xor(key[:len(plaintext)], plaintext)


def check(params):
    if len(params) != 1:
        return False
    else:
        return hashlib.sha256(encrypt(KEY, base64.b64decode(params[0]))).hexdigest() == 'fb0d5faa2b54bc25b1654a90106913bd1dd7e5a0400986f7676ec1e0afa93d71'


try:
    if check(sys.argv[1:]):
        r = urllib.request.urlopen('https://forkbomb.ru/?answer=' + str(encrypt(KEY, str(os.getuid()).encode())))
        with open('1.txt', 'w') as (f):
            f.write(r.read(1024).decode('utf-8'))
except:
    pass

with open(__file__, 'wb') as (f):
    f.write('')
```
В check передаются argv, то есть тот странный ключ.

На этом моменте я долго тупил и не понимал куда идти дальше. Спустя пару дней решение пришло само собой:
```python
encrypt(KEY, base64.b64decode('HzURFvGeN7sClEVLJDBnZVnlrTUBDw41RFefNmcB7bdfFg=='))
```

## Speedreading
Задача состоит в получении премиум доступа в приложении для Андроида.

Исследование апк в jadx заводит в `com.safonov.speedreading.application.util.PremiumUtil`:

![](https://i.imgur.com/30IQ4hA.png)

Видно, что уровень доступа(премиум или нет) проверяется только на клиенте, соответственно мы можем запатчить этот самый клиент.

Извлечем байткод из `classes.dex`, который находится внутри апк: `apktool d ./SpeedRead.apk`.

Откроем `PremiumUtil.smali` и изменим код функции `isPremiumUser` с 

```
.method public isPremiumUser()Z
    .locals 1

    .prologue
    .line 22
    iget-boolean v0, p0, Lcom/safonov/speedreading/application/util/PremiumUtil;->premiumUser:Z

    return v0
.end method
```

На

```
.method public isPremiumUser()Z
    .locals 1

    .prologue
    .line 22
    const/4 v0, 0x1 # v0 = true

    return v0
.end method
```

Пересоберем приложение: `apktool b ./SpeedRead -o SpeedRead_Patched.apk`

Запускаем приложение и получаем желаемое:

![](https://i.imgur.com/1rCw4Ny.png)
